2

a がブロック内で呼び出された場合、ブロックの最後にusingヒットしますか? return例えば、

using( var ur = new UnmanagedResource() )
{
  if( SomeCondition == true ){
   return SomeReturnValue;
  }
}

SomeConditionがの場合true、が呼び出されるUnmanagedResource前に using ブロックの最後から破棄されますか? returnこのシナリオで行われる舞台裏の操作の順序は?

4

7 に答える 7

3

「リターンが呼び出される前」が何を意味するのかわかりません。「呼び出される」は関数に起こることであり、「戻り」と呼ばれる関数はありません。このreturnステートメントがプログラムに現れると、いくつかのことが起こります。

  1. 戻り値の式が評価され、格納されます。
  2. 実行は呼び出し元に戻ります。

巻き戻しusingfinallyブロックは、ステップ 1 と 2 の間で発生します。

于 2012-08-17T18:27:32.460 に答える
2

finallyブロックは、コントロールが using ブロックを離れる前に実行されます。

実際にコンパイルされるコードは次のとおりです。

var ur = new UnmanagedResource()

try
{        
    if( SomeCondition == true ){
        return SomeReturnValue;
    }
}
finally
{
   ur.Dispose();
}
于 2012-08-17T18:27:03.973 に答える
1

あなたが探していると思われる操作の順序は次のとおりです。

  1. returnステートメントに到達します。
  2. 返される値は計算されてスタックに格納され、関数から制御が戻ったときに使用されます。
  3. コントロールはブロックを離れる準備をすることで、関連する を呼び出すブロック内でusing暗黙的な を実行します。finallyusing.Dispose()
  4. 制御は関数を離れ、呼び出し元の関数はスタック上の値にアクセスします。

これにより、予期しない結果が生じる場合があることに注意してください。たとえば、次のようなことをするとします。

using (var db = new SomeLinqDataContext())
    return db.Somethings;

この場合、戻り値は実際の値ではなく、リソースへのある種の遅延実行「ポインター」です (私が慣れていない公式の用語があるはずです)。ただし、そのリソースは、その実行が行われる前に破棄されています。(にreturn達した後、呼び出し元の関数が返された結果を評価する前に破棄されます。)したがって、破棄されたリソースにアクセスしようとするとエラーが発生します。

于 2012-08-17T18:33:57.800 に答える
1

オブジェクトは、制御フローがメソッドの呼び出し元に戻る前に破棄されます。

これについては、C# 言語仕様のセクション 8.9 で詳しく説明されています。

jump ステートメントの実行は、間に try ステートメントが存在するため複雑になります。このような try ステートメントがない場合、jump ステートメントは無条件に jump ステートメントからそのターゲットに制御を移します。このような中間の try ステートメントが存在する場合、実行はより複雑になります。jump ステートメントが、関連する finally ブロックを持つ 1 つ以上の try ブロックを終了する場合、制御は最初に、最も内側の try ステートメントの finally ブロックに転送されます。制御が finally ブロックの終点に到達すると、制御は次の外側の try ステートメントの finally ブロックに転送されます。このプロセスは、間にあるすべての try ステートメントの finally ブロックが実行されるまで繰り返されます。

...

制御が jump ステートメントのターゲットに転送される前に、2 つの try ステートメントに関連付けられた finally ブロックが実行されます。

using ステートメントは try/finally に変換されるため (詳細は 8.13 を参照)、これはDispose呼び出しが「リターンの前」に発生することが保証されていることを意味します (むしろ、制御フローがこのメソッドの呼び出し元にジャンプする前に)。 「ジャンプステートメント」。

于 2012-08-17T18:31:11.287 に答える
1

ブロックを離れると破棄されます。} でブロックを離れない場合、戻り時にそこに破棄されます (だから私の先生は私に言いました:))

于 2012-08-17T18:27:11.007 に答える
1

内部で return が呼び出された場合、using ブロックの最後はヒットしますか?

はい。

usingは、 (通常の状況では) 例外の有無にかかわらず実行されることが保証さtry/finallyれているシーケンスに変換されます。finally

于 2012-08-17T18:27:28.853 に答える
1

ブレンダン・エンリックのブログより:-

今日、いくつかのコードを書いているときに、using ステートメント内から戻る必要がありました。このようなことをしていると、いつも using ステートメントとその素晴らしさに感謝するので、ここでそれについて書くことにしました。多くの人が知っているように、C# の using ステートメントは、アンマネージ リソースにアクセスする型を管理するための優れたツールです。これらの例としては、SqlConnections、FileReaders、および他の多くの同様のタイプがあります。これらの鍵は、それらすべてが IDisposable インターフェイスを実装していることです。これは、それらを使用した後、すべてを慎重にクリーンアップする必要があることを意味します。

using ステートメントは、実行がどのように完了しても、宣言されたオブジェクトが破棄されることを保証するため、優れています。using ステートメント、throw と例外、または関数からの戻りの終了を示す終了中かっこに到達した場合でも、using ステートメントは dispose メソッドを呼び出し、オブジェクトをクリーンアップします。

dispose メソッドが起動するかどうかを気にすることなく、using ステートメント内から直接戻ることができたので、これは私のコードでは重要でした。管理されていないリソースにアクセスするオブジェクトを使用するときはいつでも、常にそれを using ステートメントに入れます。

オブジェクトが正しく破棄されることが保証されるため、using ステートメントを使用することは非常に重要です。オブジェクトのスコープは using ステートメントの範囲になります。オブジェクトのスコープ中は、using ステートメントで定義されている場合は読み取り専用になります。アンマネージドを管理するこの重要なオブジェクトが変更または再割り当てされるのを防ぐため、これも非常に優れています。

using ステートメントが優れているため、これは安全に実行できます。どのリターンをヒットしても、XmlReader が正しく破棄されることがわかります。

using (XmlReader reader = XmlReader.Create(xmlPath))
{
    // ... Do some work...
    if (someCase)
        return 0;
    // ... Do some work...
    if (someOtherCase)
        return 1;
}
return -1;

彼のもう 1 つのブログでは、実際の例を示しています。

于 2012-08-17T18:35:39.013 に答える