Programing

catch 블록에서 예외를 던지면 마지막으로 언제 실행됩니까?

crosscheck 2020. 7. 15. 07:42
반응형

catch 블록에서 예외를 던지면 마지막으로 언제 실행됩니까?


try {
   // Do stuff
}
catch (Exception e) {
   throw;
}
finally {
   // Clean up
}

위의 블록에서 finally 블록은 언제 호출됩니까? e를 던지기 전에 또는 마지막으로 부름을 받아 붙잡는가?


e가 다시 던져진 후 (즉, catch 블록이 실행 된 후) 호출됩니다.

이 7 년 후 편집 – 한 가지 중요한 점은 etry / catch 블록에 의해 호출 스택을 더 이상 잡지 않거나 전역 예외 처리기에 의해 처리 되지 않으면 finally블록 전혀 실행될 없다는 것입니다.


시도해 보지 않겠습니까?

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");
    }
}

최종 대답은 같이 여기에 대한 답변을 모두 읽은 후에는 보이는 것이 달려있다 :

  • catch 블록 내에서 예외를 다시 발생시키고 해당 예외가 다른 catch 블록 내에서 포착되면 모든 것이 문서에 따라 실행됩니다.

  • 그러나 다시 자르기 예외가 처리되지 않으면 최종 실행은 절대 실행되지 않습니다.

이 코드 샘플을 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 블록 내부에서 다시 던지기 :
--outer try
---- inner try
---- inner catch
---- inner finally
--outer catch
--outer finally
Huzzah!

예 2 : 다른 try 블록 외부에서 다시 던지기 :
--try
--catch

처리되지 않은 예외 : System.Exception : 'System.Exception'유형의 예외가 발생했습니다.
C : \ local source \ ConsoleApplication1 \ Program.cs : line의 ConsoleApplication1.Program.Main ()에서 53


귀하의 예는 다음 코드와 동일하게 작동합니다.

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

참고URL : https://stackoverflow.com/questions/1555567/when-is-finally-run-if-you-throw-an-exception-from-the-catch-block

반응형