在catch中最后抛出异常。 CLR行为与try-catch块

时间:2017-05-05 10:34:15

标签: c# .net exception try-catch clr

我写了简单的C#console app:

class Mystery
{
    static void Main(string[] args)
    {
        MakeMess();
    }

    private static void MakeMess()
    {
        try
        {
            System.Console.WriteLine("try");
            throw new Exception(); // let's invoke catch
        }
        catch(Exception)
        {
            System.Console.WriteLine("catch");
            throw new Exception("A");
        }
        finally
        {
            System.Console.WriteLine("finally");
            throw new Exception("B");
        }
    }
}

控制台中给出的输出是:

  

     

捕获

     

未处理的异常:System.Exception:A中的Mystery.Program.MakeMess()...

CLR似乎抓住了 A ,并且根本没有调用finally块。

但是当我用try-catch块包围对MakeMess()的调用时:

static void Main(string[] args)
{
    try
    {
        MakeMess();
    }
    catch(Exception ex)
    {
        System.Console.WriteLine("Main caught " + ex.Message);
    }
}

输出看起来完全不同:

  

     

捕获

     

最后

     

主要抓住了B

当在方法之外严格处理Exception时,似乎从MakeMess()传播的异常是不同的。

这种行为的解释是什么?

1 个答案:

答案 0 :(得分:2)

您所看到的行为与finally块投掷无关。你只是在你的应用程序中有一个未处理的异常,当发生这种情况时,所有的赌注都会被取消,包括是否运行finally块:

来自MSDN文档:

  

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

     

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

如果finally块必须运行,那么解决方案就是准确地完成你在第二个片段中所做的事情:处理未处理的异常。