我有以下代码
using(MemoryStream ms = new MemoryStream())
{
//code
return 0;
}
该方法在语句大括号dispose()
的末尾调用,对吗?由于我 在语句结束之前,对象会被正确处理吗?这里会发生什么?using
}
return
using
MemoryStream
我有以下代码
using(MemoryStream ms = new MemoryStream())
{
//code
return 0;
}
该方法在语句大括号dispose()
的末尾调用,对吗?由于我 在语句结束之前,对象会被正确处理吗?这里会发生什么?using
}
return
using
MemoryStream
是的,Dispose
将被调用。一旦执行离开块的范围,它就会被调用using
,无论它以什么方式离开块,无论是块执行结束,return
语句还是异常。
正如@Noldorin 正确指出的那样,using
在代码中使用块被编译成try
/ finally
,并Dispose
在块中被调用finally
。例如下面的代码:
using(MemoryStream ms = new MemoryStream())
{
//code
return 0;
}
有效地变成:
MemoryStream ms = new MemoryStream();
try
{
// code
return 0;
}
finally
{
ms.Dispose();
}
因此,因为finally
保证在try
块完成执行后执行,无论其执行路径如何,Dispose
都保证被调用,无论如何。
有关详细信息,请参阅此 MSDN 文章。
附录:
只是要补充一点:因为Dispose
保证会被调用,所以确保Dispose
在实现时永远不会抛出异常几乎总是一个好主意IDisposable
。不幸的是,核心库中有一些类在调用时会在某些情况下抛出Dispose
——我在看你,WCF 服务参考/客户端代理!Dispose
- 当这种情况发生时,如果在异常堆栈展开期间调用了原始异常,则可能很难追踪到原始异常,因为原始异常被吞没,有利于Dispose
调用生成的新异常。这可能会令人沮丧。还是那令人沮丧的疯狂?两者之一。也许两者兼而有之。
using
语句的行为与try ... finally
块完全相同,因此将始终在任何代码退出路径上执行。但是,我相信它们会受到很少和罕见finally
的不调用块的情况的影响。我记得的一个例子是,如果前台线程在后台线程处于活动状态时退出:除了 GC 之外的所有线程都被暂停,这意味着finally
块没有运行。
明显的编辑:除了让它们处理 IDisposable 对象的逻辑之外,它们的行为相同,d'oh。
奖励内容:它们可以堆叠(类型不同):
using (SqlConnection conn = new SqlConnection("string"))
using (SqlCommand comm = new SqlCommand("", conn))
{
}
还有逗号分隔(类型相同):
using (SqlCommand comm = new SqlCommand("", conn),
comm2 = new SqlCommand("", conn))
{
}
您的 MemoryStream 对象将被正确处理,无需担心。
使用该using
语句,无论完成路径如何,都将处理该对象。
进一步阅读...
编译后查看反射器中的代码。您会发现编译器重构代码以确保在流上调用 dispose。