When is finally run if you throw an exception from the catch block?

后端 未结 7 1514
没有蜡笔的小新
没有蜡笔的小新 2020-11-28 05:06
try {
   // Do stuff
}
catch (Exception e) {
   throw;
}
finally {
   // Clean up
}

In the above block when is the finally block called? Before the

相关标签:
7条回答
  • 2020-11-28 05:11

    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
    --catch

    Unhandled Exception: System.Exception: Exception of type 'System.Exception' was thrown.
    at ConsoleApplication1.Program.Main() in C:\local source\ConsoleApplication1\Program.cs:line 53

    0 讨论(0)
  • 2020-11-28 05:17

    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.

    0 讨论(0)
  • 2020-11-28 05:32

    Why not try it:

    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");
        }
    }
    
    0 讨论(0)
  • A simple way to tell also is to debug your code and notice when finally is called.

    0 讨论(0)
  • 2020-11-28 05:34

    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.

    0 讨论(0)
  • 2020-11-28 05:37

    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.

    0 讨论(0)
提交回复
热议问题