C#中的嵌套try-finally

24

为什么“Console.WriteLine("asdf");”这一行没有被执行?其他所有语句都被执行了。难道不应该被执行,因为我们无法跳出finally块吗?

static bool Func()
{
    try
    {
        try
        {
        }
        finally
        {
            try
            {
                throw new ApplicationException();
            }
            finally
            {
                Console.WriteLine("asd");
            }

            Console.WriteLine("asdf");
        }
    }
    finally
    {
        Console.WriteLine("asd");
    }
}

7个回答

30

finally代码块仅在try代码块抛出异常时(至少大部分情况是如此,参见下面MSDN的摘录)保证会被执行。如果你在finally代码块中抛出异常,该异常将导致控制流离开finally代码块,其中其余代码将不会执行。

在您的情况下,未执行的代码行位于同一finally代码块中的异常之后,因此它被跳过了。

来自MSDN - try-finally:

finally代码块用于清理在try代码块中分配的任何资源,以及运行必须执行的任何代码,即使try代码块中发生异常也是如此。通常,finally代码块的语句在控制离开try语句时执行,无论控制转移的原因是正常执行,还是执行break、continue、goto或return语句,或者通过传播异常离开try语句。

在处理异常时,关联的finally代码块保证会被执行。然而,如果异常未处理,则finally代码块的执行取决于如何触发异常取消操作。这反过来又取决于计算机的设置。有关详细信息,请参阅CLR中的未处理异常处理。

注意: CLR中未处理的异常处理是指MSDN Magazine 2008年9月份期刊中的一篇文章。所有2008年及更早期的MSDN Magazine期刊都只能以.chm文件形式获取,需下载后才能查看。


“finally块仅保证剪断,即它们将在try块抛出异常时进入” 您的意思是finally块只会在try块退出后进入吗? (catch块对异常执行) - James Khoury
1
这是真的。我试图指出他们如何处理异常,以及他们不能保证它们会完全运行,但至少会被输入。 - Jon Senchyna
查看文章MSDN Magazine 2008年9月:CLR中的未处理异常处理。(打开chm文件需要解锁:文件属性->常规->解锁) - vladimir

19

我认为最好的回答方法是使用代码,因此以下图像可作参考 输入图像描述


7
谢谢您的夸奖,这张精彩的图片确实具有千言万语的力量。 - James Khoury
我认为它被最外层的 try 块捕获,finally 没有捕获任何异常。 - Kocsis Dávid

6

由于异常是在finally块中抛出的,所以它导致控制权落到最终的finally块。因此,“asdf” WriteLine从未执行。


4

在finally(或catch)块内抛出的异常会取消该finally(或catch)块的其余部分。


3

错误发生在第三个try块中,导致其相应的finally被执行。然而,这会使它从当前finally中出错,并被原始的try-finally块捕获。


1

因为您已经将代码放在了try块中,所以它将执行finally块,并输出Console.WriteLine("asd");,然后退出到外部的try catch块。


-1
当我在不同的主机平台上部署代码时,使用try-finally块,我发现: 当try块中未抛出异常时。

一些Windows平台始终执行finally块, 而有些平台则从未执行finally块。

我的finally块包含关闭错误日志的指令,未能执行finally块总是在退出时引发另一个异常,只留下难以理解的信息来找出导致错误的原因。 对于我的应用程序,try finally块带来的麻烦比它们的价值更高。

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