如果我在 using 语句结束之前返回会发生什么?会调用 dispose 吗?
我有以下代码
using(MemoryStream ms = new MemoryStream())
{
//code
return 0;
}
dispose()
方法是在 using
语句大括号 }
末尾调用的,对吧?由于我在 using
语句结束之前 return
,MemoryStream
对象会被正确处理吗?这里会发生什么?
I've the following code
using(MemoryStream ms = new MemoryStream())
{
//code
return 0;
}
The dispose()
method is called at the end of using
statement braces }
right? Since I return
before the end of the using
statement, will the MemoryStream
object be disposed properly? What happens here?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
是的,
Dispose
将被调用。一旦执行离开using
块的范围,它就会被调用,无论使用什么方式离开该块,无论是块执行结束还是return 语句,或异常。
正如 @Noldorin 正确指出的那样,在代码中使用
using
块会被编译为try
/finally
,并使用Dispose
在finally
块中被调用。例如,以下代码:实际上变为:
因此,由于
finally
保证在try
块执行完毕后执行,无论其执行路径如何,Dispose<无论如何,/code> 都保证被调用。
有关详细信息,请参阅这篇 MSDN 文章。
附录:
需要添加一点警告:因为保证调用
Dispose
,所以在实现IDisposable 时确保
。不幸的是,核心库中有一些类在调用Dispose
永远不会抛出异常几乎总是一个好主意Dispose
时确实会在某些情况下抛出 - 我正在看着你,WCF 服务参考/客户端代理! -- 当发生这种情况时,如果在异常堆栈展开期间调用Dispose
,则很难追踪原始异常,因为原始异常会被生成的新异常所吞噬。 code>Dispose
调用。这可能会让人非常沮丧。或者这令人沮丧、疯狂?两者之一。也许两者都有。Yes,
Dispose
will be called. It's called as soon as the execution leaves the scope of theusing
block, regardless of what means it took to leave the block, be it the end of execution of the block, areturn
statement, or an exception.As @Noldorin correctly points out, using a
using
block in code gets compiled intotry
/finally
, withDispose
being called in thefinally
block. For example the following code:effectively becomes:
So, because
finally
is guaranteed to execute after thetry
block has finished execution, regardless of its execution path,Dispose
is guaranteed to be called, no matter what.For more information, see this MSDN article.
Addendum:
Just a little caveat to add: because
Dispose
is guaranteed to be called, it's almost always a good idea to ensure thatDispose
never throws an exception when you implementIDisposable
. Unfortunately, there are some classes in the core library that do throw in certain circumstances whenDispose
is called -- I'm looking at you, WCF Service Reference / Client Proxy! -- and when that happens it can be very difficult to track down the original exception ifDispose
was called during an exception stack unwind, since the original exception gets swallowed in favor of the new exception generated by theDispose
call. It can be maddeningly frustrating. Or is that frustratingly maddening? One of the two. Maybe both.using
语句的行为与try ...finally
块完全相同,因此将始终在任何代码退出路径上执行。但是,我相信它们会遇到极少数且罕见的情况,其中finally
块未被调用。我记得的一个例子是,如果前台线程退出而后台线程处于活动状态:除了 GC 之外的所有线程都将暂停,这意味着finally
块不会运行。明显的编辑:除了让它们处理 IDisposable 对象的逻辑之外,它们的行为是相同的,d'oh。
奖励内容:它们可以堆叠(类型不同):
也可以用逗号分隔(类型相同):
using
statements behave exactly liketry ... finally
blocks, so will always execute on any code exit paths. However, I believe they are subject to the very few and rare situations in whichfinally
blocks are not called. One example that I can remember is if the foreground thread exits while background threads are active: all threads apart from the GC are paused, meaningfinally
blocks are not run.Obvious edit: they behave the same apart from the logic that lets them handle IDisposable objects, d'oh.
Bonus content: they can be stacked (where types differ):
And also comma-delimited (where types are the same):
您的 MemoryStream 对象将被正确处理,无需担心。
Your MemoryStream object will be disposed properly, no need to worry about that.
使用
using
语句,无论完成路径如何,该对象都将被释放。进一步阅读...
With the
using
statement, the object will be disposed of regardless of the completion path.Further reading...
编译后在反射器中查看代码。您会发现编译器重构了代码以确保在流上调用 dispose。
Take a look at your code in reflector after you compile it. You'll find that the compiler refactors the code to ensure that dispose is called on the stream.