C#에서 throw는 키워드로, 프로그램 실행 중에 예외를 수동으로 발생시킬 때 사용됩니다. 이렇게 발생된 예외는 요구 사항에 따라 try-catch 블록을 사용하여 처리할 수 있습니다.
catch 블록 안에서 throw 키워드를 사용하면 해당 블록에서 처리한 예외를 다시 던질(re-throw) 수 있습니다. 예외를 다시 발생시키는 것은 호출자(caller)가 자신의 방식대로 예외를 처리할 수 있도록 예외를 전달하고 싶을 때 유용합니다.
throw;와 throw ex;의 차이점
여기서 중요한 점은 스택 추적(stack trace)의 보존 여부입니다.
throw;— 원래 예외 객체를 그대로 다시 던지기 때문에 기존의 스택 추적 정보가 그대로 유지됩니다.throw ex;— 새로운 예외처럼 취급되어 현재 위치부터 스택 추적이 다시 시작되므로, 원래 예외가 발생한 지점의 정보가 손실됩니다.
따라서 스택 추적을 잃지 않고 예외를 다시 발생시키려면 반드시 throw;를 사용해야 합니다.
예제 코드
다음은 C#에서 try-catch 블록과 throw 키워드를 사용하여 예외를 호출자에게 다시 전달하는 예제입니다.
class Program{
static void Main(string[] args){
try{
Method2();
}
catch (System.Exception ex){
System.Console.WriteLine($"{ex.StackTrace.ToString()} {ex.Message}");
}
Console.ReadLine();
}
static void Method2(){
try{
Method1();
}
catch (System.Exception){
throw;
}
}
static void Method1(){
try{
throw new NullReferenceException("Null Exception error");
}
catch (System.Exception){
throw;
}
}
}위 코드에서 Method1()에서 발생한 NullReferenceException은 catch 블록의 throw;에 의해 그대로 다시 던져지고, Method2()의 catch 블록에서도 마찬가지로 throw;를 통해 호출자인 Main 메서드로 전달됩니다. 이 과정에서 원래 예외가 발생한 지점의 스택 추적 정보는 손실되지 않습니다.
실행 결과
at DemoApplication.Program.Method1() in C:\Users\Koushik\Desktop\Questions\ConsoleApp\Program.cs:line 49 at DemoApplication.Program.Method2() in C:\Users\Koushik\Desktop\Questions\ConsoleApp\Program.cs:line 37 at DemoApplication.Program.Main(String[] args) in C:\Users\Koushik\Desktop\Questions\ConsoleApp\Program.cs:line 24 Null Exception error
실행 결과를 보면 예외가 Method1(), Method2(), Main()을 거치며 전달되었음에도 불구하고, 최초 예외 발생 지점(Method1())의 정확한 파일 경로와 라인 번호가 모두 출력되는 것을 확인할 수 있습니다.
정리
C#에서 예외를 다시 발생시킬 때 스택 추적을 유지하려면 catch 블록에서 매개변수 없이 throw;만 사용하는 것이 올바른 방법입니다. 반면 throw ex;와 같이 작성하면 스택 추적이 재설정되어 디버깅 시 실제 오류 발생 지점을 찾기 어려워질 수 있으므로 주의해야 합니다.