C#的Using语句如何转化为Try-Finally

5
我正在努力理解这个问题。根据关于Using语句的此页面所述:
使用Using语句可以确保在调用对象方法时发生异常时也会调用Dispose方法。您可以通过将对象放在try块内,然后在finally块中调用Dispose来实现相同的结果;实际上,这就是编译器如何将Using语句转换的方式。
但是,在关于Try-Finally块的此页面中指出:
在受处理的异常中,相关联的finally块保证被运行。然而,如果异常未受处理,则执行finally块取决于异常取消操作的触发方式。
那么,如果Using语句被转换为不保证调用finally语句的Try-Finally语句,它怎么能保证在发生异常时调用Dispose方法呢?

不是答案,因为我不确定自己是否正确,但我认为它的意思是,如果在catch语句中有未处理的异常,那么finally将不会被调用。但是使用autocreated创建的catch语句只有一个dispose()调用。 - GendoIkari
@GendoIkari:不,这与异常抛出的位置无关,而是与它是否最终被捕获有关。最终被捕获(处理)的异常将始终调用finally块(即使从catch中抛出另一个异常)。令人惊讶的是,未处理的异常可能会或可能不会调用finally块。 - Cameron
@Cameron:谢谢。我想我假设如果你有一个finally,那么你也在处理异常。但我想这是可能的,有一个只处理特定异常的catch;或者一个没有catch的try/finally。 - GendoIkari
@code4life,不,我不是一个巨魔。在工作中编写代码时,我想更好地理解using语句的工作原理。我发现它转换为try-finally很有趣。但这让我感到困惑,因为我上面提到的原因。此外,我为什么要做那么多研究来恶作剧呢? - TrueEddie
@TrueEddie:很抱歉,我删掉了我的评论。话虽如此,我感觉你并没有真正尝试用简单的程序测试你的问题。如果我错了,我向你道歉。 - code4life
3个回答

10

它真的像try/finally一样运行 - 所以如果应用程序终止,资源可能没有被释放...这通常是可以接受的,因为通常处理器会释放进程持有的资源...并且操作系统在进程死亡时也会清理这些资源。(这并不意味着Dispose方法不会被调用...它和普通的try/finally一样。)

显然,如果您在文件系统上有一个“锁定文件”或类似的东西,那就有问题了 - 但如果面对断电等情况,您将遇到相同的问题。


1
我认为可能原帖的作者认为“未处理”意味着“在立即的try/finally块中未被捕获”,而不是“整个应用程序未处理”。 - adv12
那么你的意思是,Using语句并不能真正保证Dispose方法会被调用,对吗? - TrueEddie
@TrueEddie:确实 - 它只能像普通的try/finally一样保证相同的程度。 - Jon Skeet

5

有些异常是程序无法恢复的,在这种情况下,finally块将不会执行。例如堆栈溢出异常或内存不足异常。


0

如果异常展开仅以未处理的导致程序崩溃的异常结束,则最终块不会运行,因为执行停止。

简而言之,只有在成功或已处理的异常时才会运行最终块。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接