如果我在使用声明结束之前返回会发生什么?处理是否会被召唤?

NLV*_*NLV 112 .net c# dispose idisposable using-statement

我有以下代码

using(MemoryStream ms = new MemoryStream())
{
     //code
     return 0;
}
Run Code Online (Sandbox Code Playgroud)

dispose()using语句括号结束时调用该方法}对吗?由于我 returnusing声明结束之前,MemoryStream对象是否会被妥善处理?这里发生了什么?

Ran*_*pho 162

是的,Dispose将被召集.一旦执行离开using块的范围,就会调用它,无论它离开块的方式是什么,无论是块的执行结束,return语句还是异常.

正如@Noldorin正确指出的那样,using在代码中使用块被编译到try/中finally,并Disposefinally块中调用.例如,以下代码:

using(MemoryStream ms = new MemoryStream())
{
     //code
     return 0;
}
Run Code Online (Sandbox Code Playgroud)

有效地变成:

MemoryStream ms = new MemoryStream();
try
{
    // code
    return 0;
}
finally
{
    ms.Dispose();
}
Run Code Online (Sandbox Code Playgroud)

因此,由于finally保证在try块完成执行后执行,无论其执行路径如何,Dispose都可以保证被调用,无论如何.

有关详细信息,请参阅此MSDN文章.

附录:
添加一点注意事项:因为Dispose保证会被调用,所以确保Dispose在实现时永远不会抛出异常几乎总是一个好主意IDisposable.不幸的是,核心库中有一些类在调用某些情况时抛出Dispose- 我在看着你,WCF服务参考/客户端代理!- 当发生这种情况时,如果Dispose在异常堆栈展开期间调用,则跟踪原始异常可能非常困难,因为原始异常被吞下以支持Dispose调用生成的新异常.这可能令人沮丧.还是令人沮丧地发疯?两个中的一个.也许两者.

  • 我认为你会发现它有效地编译成了一个try-finally块,最后调用了'Dispose`,所以它正在有效地解决`finally`的实现,正如你所描述的那样. (4认同)

Ada*_*rth 18

using语句的行为与try ... finally块完全相同,因此将始终在任何代码出口路径上执行.但是,我相信它们会受到极少数罕见的情况的影响finally.我记得的一个例子是前台线程在后台线程处于活动状态时退出:除了GC之外的所有线程都被暂停,这意味着finally块不会运行.

显而易见的编辑:它们的行为与允许它们处理IDisposable对象的逻辑相同,但是哦.

奖励内容:它们可以堆叠(类型不同):

using (SqlConnection conn = new SqlConnection("string"))
using (SqlCommand comm = new SqlCommand("", conn))
{

}
Run Code Online (Sandbox Code Playgroud)

并且还以逗号分隔(类型相同):

using (SqlCommand comm = new SqlCommand("", conn), 
       SqlCommand comm2 = new SqlCommand("", conn))
{

}
Run Code Online (Sandbox Code Playgroud)