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()方法保证第二个被调用?(基本上: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 方法将在 using 范围的末尾被调用,因此 Dispose() 方法的调用顺序与它们所属对象的分配顺序相反

于 2011-10-28T03:24:38.623 回答