如果finally块抛出异常,到底会发生什么?
具体来说,如果在finally块中途抛出异常会发生什么。这个块中的其余语句(之后)是否被调用?
我知道异常会向上传播。
如果finally块抛出异常,到底会发生什么?
具体来说,如果在finally块中途抛出异常会发生什么。这个块中的其余语句(之后)是否被调用?
我知道异常会向上传播。
当前回答
对于这样的问题,我通常在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");
}
}
}
当您运行程序时,您将看到执行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");
}
}
}
正如你可以从输出中看到的,内部异常被“丢失”(即被忽略):
Inner finally block Outer catch block handling exception thrown from finally block. Outer finally block
其他回答
在另一个异常活动时抛出异常将导致第一个异常被第二个(稍后)异常所取代。
下面是一些代码,说明发生了什么:
public static void Main(string[] args)
{
try
{
try
{
throw new Exception("first exception");
}
finally
{
//try
{
throw new Exception("second exception");
}
//catch (Exception)
{
//throw;
}
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
运行代码,您将看到“第二个异常” 取消try和catch语句的注释,您将看到“第一个异常” 也取消注释抛出;语句,您将再次看到“第二个异常”。
对于这样的问题,我通常在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");
}
}
}
当您运行程序时,您将看到执行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");
}
}
}
正如你可以从输出中看到的,内部异常被“丢失”(即被忽略):
Inner finally block Outer catch block handling exception thrown from finally block. Outer finally block
异常向上传播,应该在更高的级别进行处理。如果不在更高的级别处理异常,应用程序将崩溃。“finally”块执行在抛出异常的地方停止。
无论是否存在异常,“finally”块都保证执行。
如果“finally”块在try块中发生异常后被执行, 如果这个异常没有被处理 如果finally块抛出异常
然后,try块中发生的原始异常将丢失。
public class Exception
{
public static void Main()
{
try
{
SomeMethod();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
public static void SomeMethod()
{
try
{
// This exception will be lost
throw new Exception("Exception in try block");
}
finally
{
throw new Exception("Exception in finally block");
}
}
}
关于细节的好文章
传播异常。
它抛出一个异常;)您可以在其他catch子句中捕获该异常。