try {
// Do stuff
}
catch (Exception e) {
throw;
}
finally {
// Clean up
}
在上面的代码块中,finally块是在哪个时候被调用?是在抛出异常e之前还是在finally被调用之后再调用catch块?try {
// Do stuff
}
catch (Exception e) {
throw;
}
finally {
// Clean up
}
在上面的代码块中,finally块是在哪个时候被调用?是在抛出异常e之前还是在finally被调用之后再调用catch块?在e被重新抛出后(即在执行catch块之后),它会被调用。
7年后编辑- 一个重要的注意点是,如果e
没有被更上层的try/catch块捕获或由全局异常处理程序处理,则finally
块可能根本不会执行。
finally
。 - Andrew不妨试一下:
这是执行下面代码的输出结果:
outer try
inner try
inner catch
inner finally
outer catch
outer finally
使用代码(格式化为垂直空间):
static void Main() {
try {
Console.WriteLine("outer try");
DoIt();
} catch {
Console.WriteLine("outer catch");
// swallow
} finally {
Console.WriteLine("outer finally");
}
}
static void DoIt() {
try {
Console.WriteLine("inner try");
int i = 0;
Console.WriteLine(12 / i); // oops
} catch (Exception e) {
Console.WriteLine("inner catch");
throw e; // or "throw", or "throw anything"
} finally {
Console.WriteLine("inner finally");
}
}
outer try
inner try
inner catch
Unhandled Exception: System.DivideByZeroException...
。 - Andrew读完所有回答后,看起来最终的答案是取决于具体情况:
如果在catch块中重新抛出异常,并且该异常在另一个catch块内被捕获,则一切都按照文档执行。
但是,如果未处理重新抛出的异常,则finally语句块不会执行。
我在VS2010 w/ C# 4.0中测试了此代码示例。
static void Main()
{
Console.WriteLine("Example 1: re-throw inside of another try block:");
try
{
Console.WriteLine("--outer try");
try
{
Console.WriteLine("----inner try");
throw new Exception();
}
catch
{
Console.WriteLine("----inner catch");
throw;
}
finally
{
Console.WriteLine("----inner finally");
}
}
catch
{
Console.WriteLine("--outer catch");
// swallow
}
finally
{
Console.WriteLine("--outer finally");
}
Console.WriteLine("Huzzah!");
Console.WriteLine();
Console.WriteLine("Example 2: re-throw outside of another try block:");
try
{
Console.WriteLine("--try");
throw new Exception();
}
catch
{
Console.WriteLine("--catch");
throw;
}
finally
{
Console.WriteLine("--finally");
}
Console.ReadLine();
}
这是输出结果:
示例1:在另一个try块中重新抛出:
--外部try块
----内部try块
----内部catch块
----内部finally块
--外部catch块
--外部finally块
恭喜!示例2:在另一个try块外重新抛出:
--try块
--catch块未处理的异常:System.Exception: 引发了类型为'System.Exception'的异常。
在C:\local source\ConsoleApplication1\Program.cs的ConsoleApplication1.Program.Main()第53行。
您的示例代码与以下代码的行为完全相同:
try {
try {
// Do stuff
} catch(Exception e) {
throw e;
}
} finally {
// Clean up
}
顺便提一句,如果您确实想要使用throw e;
(也就是抛出您刚捕获的同一个异常),那么最好只使用throw;
,因为这样会保留原始的堆栈跟踪而不会创建一个新的。
finally
块也会在catch
块之后运行,这正是我的代码片段要说明的。 - Daniel Prydentry
块内,我的答案有一个“try-catch”。我试图通过使用两个2部分结构来解释3部分结构的行为。我没有看到原始问题中有第二个try
块的任何迹象,所以我不明白你从哪里得到了那个。 - Daniel Pryden如果在 catch 处理程序块内发生未处理的异常,则 finally 块将完全不会被调用。
static void Main(string[] args)
{
try
{
Console.WriteLine("in the try");
int d = 0;
int k = 0 / d;
}
catch (Exception e)
{
Console.WriteLine("in the catch");
throw;
}
finally
{
Console.WriteLine("In the finally");
}
}
输出:
C:\users\administrator\documents\TestExceptionNesting\bin\Release>TestExceptionNesting.exe
在 try 中
在 catch 中
未处理的异常: System.DivideByZeroException: 尝试除以零。 在 C:\users\administrator\documents\TestExceptionNesting\TestExceptionNesting.cs 的 TestExceptionNesting.Program.Main(String[] args) 第22行
C:\users\administrator\documents\TestExceptionNesting\bin\release>
今天在面试中被问到这个问题,面试官反复问我“你确定 finally 没有被调用吗?” 我不确定这是否是一个诡计问题,还是面试官有其他想法并且写了错误的代码让我调试。为了安心,我回家尝试了一下(编译和运行,没有调试交互)。
using System;
class Program
{
static void Main()
{
FinallyThrow();
Console.ReadLine();
}
static void FinallyThrow()
{
// Get finally block to execute EVEN IF there is an unhandled exception
Exception thrownEx = null;
try
{
Console.WriteLine("try..");
throw new InvalidOperationException();
}
catch (Exception ex)
{
Console.WriteLine("catch..");
thrownEx = ex;
}
finally
{
Console.WriteLine("finally..");
if (thrownEx != null) throw thrownEx;
}
}
}
输出(在未处理异常后)
try..
catch..
finally..
使用C#控制台应用程序进行测试,finally代码在抛出异常后被执行:存在“应用程序错误对话框”,并在选择“关闭程序”选项后,在控制台窗口中执行了finally块。 但是,在finally代码块内设置断点后,我永远无法触发它。调试器一直停在throw语句处。 以下是我的测试代码:
class Program
{
static void Main(string[] args)
{
string msg;
Console.WriteLine(string.Format("GetRandomNuber returned: {0}{1}", GetRandomNumber(out msg), msg) == "" ? "" : "An error has occurred: " + msg);
}
static int GetRandomNumber(out string errorMessage)
{
int result = 0;
try
{
errorMessage = "";
int test = 0;
result = 3/test;
return result;
}
catch (Exception ex)
{
errorMessage = ex.Message;
throw ex;
}
finally
{
Console.WriteLine("finally block!");
}
}
}