When is finally run if you throw an exception from the catch block?
try {
// Do stuff
}
catch (Exception e) {
throw;
}
finally {
// Clean up
}
In the above block when is the finally block called? Before 开发者_JAVA百科the throwing of e or is finally called and then catch?
It would be called after e is re-thrown (i.e. after the catch block is executed)
editing this 7 years later - one important note is that if e
is not caught by a try/catch block further up the call stack or handled by a global exception handler, then the finally
block may never execute at all.
Why not try it:
This is the output from executing the code below:
outer try
inner try
inner catch
inner finally
outer catch
outer finally
with code (formatted for vertical space):
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");
}
}
After reading all of the answers here it looks like the final answer is it depends:
If you re-throw an exception within the catch block, and that exception is caught inside of another catch block, everything executes according to the documentation.
However, if the re-trown exception is unhandled, the finally never executes.
I tested this code sample in 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();
}
Here is the output:
Example 1: re-throw inside of another try block:
--outer try
----inner try
----inner catch
----inner finally
--outer catch
--outer finally
Huzzah!Example 2: re-throw outside of another try block:
--try
--catchUnhandled Exception: System.Exception: Exception of type 'System.Exception' was thrown.
at ConsoleApplication1.Program.Main() in C:\local source\ConsoleApplication1\Program.cs:line 53
Your example would behave identically to this code:
try {
try {
// Do stuff
} catch(Exception e) {
throw e;
}
} finally {
// Clean up
}
As a side note, if you really mean throw e;
(that is, throw the same exception you just caught), it is much better to just do throw;
, since that will preserve the original stack trace instead of creating a new one.
If there is an unhandled exception inside a catch handler block, the finally block gets called exactly zero times
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");
}
}
Output:
C:\users\administrator\documents\TestExceptionNesting\bin\Release>TestExceptionNesting.exe
in the try
in the catch
Unhandled Exception: System.DivideByZeroException: Attempted to divide by zero. at TestExceptionNesting.Program.Main(String[] args) in C:\users\administrator\documents\TestExceptionNesting\TestExceptionNesting.cs:line 22
C:\users\administrator\documents\TestExceptionNesting\bin\release>
I got asked this question today at an interview and the interviewer kept going back "are you sure the finally doesn't get called?" I was uncertain if it was meant a trick question or the interviewer had something else in mind and wrote the wrong code for me to debug so I came home and tried it (build and run, no debugger interaction), just to put my mind at rest.
A simple way to tell also is to debug your code and notice when finally is called.
Testing with a C# Console Application, the finally code has been executed after the exception is thrown: The "Application Error Dialog" existed and after you chose "Close the program" option, the finally block was executed in that console window. But setting the breaking point inside the finally code block, I can never hit it. The debugger keeps stopping at the throw statement. Here is my test code:
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!");
}
}
}
Debugging in VS2010 - .NET Framework 4.0
You can do it, I have done this to ensure cleanup.
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;
}
}
}
OUTPUT (after breaking to the unhandled exception)
try..
catch..
finally..
.Finally always run even if unhandled exception
精彩评论