4
using (Stuff1 stf1 = new Stuff1(...)) // Allocation of stf1
using (Stuff2 stf2 = new Stuff2(...)) // Allocation of stf2
{
    try
    {
        // ... do stuff with stf1 and stf2 here ...
    }
    catch (Stuff1Exception ex1)
    {
        // ...
    }
    catch (Stuff2Exception ex2)
    {
        // ...
    }
} // Automatic deterministic destruction through Dispose() for stf1/stf2 - but in which order?

つまり、stf2 の Dispose() メソッドが最初に呼び出されることが保証され、次に stf1 の Dispose() メソッドが 2 番目に呼び出されることが保証されますか? (基本的に: Dispose() メソッドは、それらが属するオブジェクトの割り当てとは逆の順序で呼び出されますか?)

4

6 に答える 6

6

using ステートメントは、他のブロック レベルのステートメントと同じです。次のようなコードを書いた場合:

if (...)
    if (...)
    {

    }

物事がどのような順序で行われるかは明らかです (特定の構造をお勧めするわけではありません)。

if (...)
{
    if(...)
    {

    }
}

だからそれはusingです。あなたのコードは次のものと同じです。

using (...)
{
    using(...)
    {

    }
}

ここでは、内側の using ブロックが最初に終了することは完全に明らかであるため、そのリソースを最初に破棄する必要があります。

于 2011-10-28T03:21:25.997 に答える
2

はい、最初に stf2.Dispose が呼び出され、その後 stf1.Dispose が呼び出されます

于 2011-10-28T03:21:32.057 に答える
2

とにかく、using ステートメントは try-finally に変換されます。その単なる構文糖衣..したがって、あなたの例はコンパイル時に次のように変換されるという点で正しいです:

try
{
    Stuff1 stf1 = new Stuff1());
    try
    {
        Stuff2 stf2 = new Stuff2();
    }
    finally
    {
        stf2.Dispose();
    }
}
finally
{
    stf1.Dispose();
}
于 2011-10-28T03:22:19.353 に答える
1

再注文の可能性があるため、保証はありません。Dispose は、終了中のカーリー (または例では暗黙のカーリー) で呼び出されます。最適化されていないデバッグ ビルドでは、期待される順序が常に表示されます。Thread.MemoryBarrierを使用して、操作の順序を強制できます。

using (Stuff1 stf1 = new Stuff1(...)) // Allocation of stf1
using (Stuff2 stf2 = new Stuff2(...)) // Allocation of stf2
{ {
    try
    {
        // ... do stuff with stf1 and stf2 here ...
    }
    catch (Stuff1Exception ex1)
    {
        // ...
    }
    catch (Stuff2Exception ex2)
    {
        // ...
    }
} Thread.MemoryBarrier(); }

リリース モードの最適化は、すべての命令が完了した後にこのスレッドで予測可能な結果が保証されるように行われます。他のすべて (別のコアの別のスレッドからのビュー) は手に入れることができます。別のスレッドから観察されるように、stf2 がまだ破棄されていないが、stf1 が破棄されている状況があることは規則に違反していません。操作の順序を強制しない限り。アサートをいくつか書いて、Jinxで実行してみてください

于 2011-10-28T03:20:21.713 に答える
1

Stuff2 は内側のブロックにあるため、Stuff1 の前に配置されます。

Stuff1 の外側のブロックでブレースを使用しませんでしたが、使用した場合と同じです。

于 2011-10-28T03:21:02.947 に答える
0

はい、Dispose メソッドは us​​ing スコープの最後で呼び出されるため、Dispose() メソッドは、それらが属するオブジェクトの割り当てとは逆の順序で呼び出されます。

于 2011-10-28T03:24:38.623 に答える