使用语句无法正常工作

alc*_*vil 6 .net c# using exception using-statement

我的名为S的类看起来像这样:

public class S : IDisposable
{
    public void Dispose()
    {
        // some code
    }

    public void f()
    {
        throw new Exception("exception");
    }
}
Run Code Online (Sandbox Code Playgroud)

当我使用using语句时,f()方法不会调用s.Dispose()方法.我认为它应该调用Dispose方法,即使发生异常.这就是我在MSDN中读到的内容:"using语句确保即使在对象上调用方法时发生异常也会调用Dispose".我错过了什么吗?

using (S s = new S())
{
    s.f();
}
Run Code Online (Sandbox Code Playgroud)

调用sf()会结束我的程序而不会丢弃我的对象.我想我不必使用try/catch,因为using语句应该为我做.

Raw*_*ing 5

我错过了什么吗?

一个using语句转换成一个try ... finally声明.

根据try ... finallyC#参考,

在处理的异常中,保证运行关联的finally块.但是,如果未处理异常,则finally块的执行取决于如何触发异常展开操作.反过来,这取决于您的计算机的设置方式.

所以是的,你错过了一些东西:一个finally块(以及Dispose一个using声明中的调用)不能保证在所有情况下都会触发,包括在你的环境中,一个未处理的异常.

该页继续建议:

通常,当未处理的异常结束应用程序时,无论finally块是否运行都不重要.但是,如果在finally块中有语句,即使在这种情况下也必须运行,一种解决方案是在try-finally语句中添加一个catch块.或者,您可以捕获可能在调用堆栈上方的try-finally语句的try块中抛出的异常.也就是说,您可以在调用包含try-finally语句的方法的方法中,或在调用该方法的方法中或在调用堆栈的任何方法中捕获异常.如果未捕获异常,则finally块的执行取决于操作系统是否选择触发异常展开操作.

如果我能在C#规范中找到引用,我会更高兴.不幸的是,我对§8.9.5的解读是,即使是未处理的异常也会导致finally堆栈上的所有语句执行.

  • 这是有道理的,因为当我使用`try/finally`块而不是`using statement`时,它也不会执行`finally`. (2认同)

InB*_*een 3

问题可能是您正在调试器中运行代码。这意味着未处理的异常之后出现的任何代码都不会被执行,因为调试器将在此时停止。

如果您在调试器之外运行测试场景,那么Dispose()当运行时清理混乱时将调用该方法。在 Dispose() 方法中放置一些代码“标记”,这将为您提供调用 Dipose 的可见标志:例如,在名为 d DisposeHasRun.yeah的某个可访问文件夹中创建一个文件(请注意,输出到控制台或 aMessageBox不是一个选项因为应用程序由于未处理的异常而退出)。当您在调试器外部运行测试用例时,您将看到该文件已创建。

也就是说,有些情况下Dispose不会被调用(也不会finally阻塞)。例如,StackOverflow由于无限递归而导致的异常将不会调用Dispose(),因为运行时将使应用程序尽快退出。(ThreadAbortException我认为会表现得一样)