Jac*_*ada 257 c# exception-handling exception try-catch-finally
如果finally块抛出异常,究竟会发生什么?
具体来说,如果在finally块的中途抛出异常会发生什么.是否调用了此块中的其余语句(之后)?
我知道异常会向上传播.
Hen*_*man 414
如果finally块抛出异常,究竟会发生什么?
该异常传播出来,并且(可以)在更高级别处理.
您的finally块将不会在抛出异常之外完成.
如果在处理早期异常期间执行finally块,则第一个异常将丢失.
C#4语言规范§8.9.5:如果finally块抛出另一个异常,则终止当前异常的处理.
Dir*_*mar 98
对于这些问题,我通常在Visual Studio中打开一个空的控制台应用程序项目并编写一个小示例程序:
using System;
class Program
{
static void Main(string[] args)
{
try
{
try
{
throw new Exception("exception thrown from try block");
}
catch (Exception ex)
{
Console.WriteLine("Inner catch block handling {0}.", ex.Message);
throw;
}
finally
{
Console.WriteLine("Inner finally block");
throw new Exception("exception thrown from finally block");
Console.WriteLine("This line is never reached");
}
}
catch (Exception ex)
{
Console.WriteLine("Outer catch block handling {0}.", ex.Message);
}
finally
{
Console.WriteLine("Outer finally block");
}
}
}
Run Code Online (Sandbox Code Playgroud)
运行程序时,您将看到执行catch和finally执行块的确切顺序.请注意,抛出异常后finally块中的代码将不会被执行(事实上,在此示例程序中,Visual Studio甚至会警告您已检测到无法访问的代码):
Inner catch block handling exception thrown from try block. Inner finally block Outer catch block handling exception thrown from finally block. Outer finally block
补充说明
正如Michael Damatov指出的那样,try如果你不在(内部)catch块中处理它,那么块中的异常将被"吃掉" .实际上,在上面的示例中,重新抛出的异常不会出现在外部catch块中.为了更清楚地看一下下面稍微修改过的样本:
using System;
class Program
{
static void Main(string[] args)
{
try
{
try
{
throw new Exception("exception thrown from try block");
}
finally
{
Console.WriteLine("Inner finally block");
throw new Exception("exception thrown from finally block");
Console.WriteLine("This line is never reached");
}
}
catch (Exception ex)
{
Console.WriteLine("Outer catch block handling {0}.", ex.Message);
}
finally
{
Console.WriteLine("Outer finally block");
}
}
}
Run Code Online (Sandbox Code Playgroud)
从输出中可以看出,内部异常是"丢失"(即忽略):
Inner finally block Outer catch block handling exception thrown from finally block. Outer finally block
保存“原始异常”(在try块中抛出)并牺牲“最终异常”(在finally块中抛出)的快速(且相当明显)片段,以防原始异常对您更重要:
try
{
throw new Exception("Original Exception");
}
finally
{
try
{
throw new Exception("Finally Exception");
}
catch
{ }
}
Run Code Online (Sandbox Code Playgroud)
执行上述代码时,“原始异常”向上传播调用堆栈,而“最终异常”丢失。