본문 바로가기
개발언어/C#

[C#] Exception 예외 처리 (try-catch-finally, throw)

by 창용이랑 2021. 7. 1.
728x90

C#을 포함한 모든 .NET 프로그래밍 언어는 .NET Framework와 Exception 메카니즘에 따라 Exception을 처리합니다.

.NET의 System.Excpetion 은 모든 Exception의 Base 클래스이며, 예외 처리는 이 Exception 객체를 기본으로 처리하게 됩니다.

만약 Exception이 발생하였는데 이를 프로그램 내에서 처리하지 않으면 프로그램은 Crash하여 종료하게 됩니다.

(이를 Unhandled Exception 이라고 부릅니다)

C#에서는 try, catch, finally라는 키워드를 사용하여 Exception을 핸들링하게 되며, 또한 throw라는 C# 키워드를 통해 Exception을 만들어 던지거나 혹은 기존 Exception을 다시 던질 수 있습니다.

위 함수는 간단하게 try-catch 구문을 사용하여 예외 처리(Exception)에 대한 메시지박스를 출력해주는 코드입니다.

doFunction() 이라는 함수에 무엇인가 에러(예외)가 발생하게 된다면 catch 문으로 들어와 Exception 타입의 ex변수에 예외처리에 대한 정보를 출력해주게 됩니다.

try-catch-finally

try 블럭은 실제 실행하고 싶은 프로그램 명령문들을 갖는 블럭입니다. 만약 여기서 어떤 에러가 발생하면, 이는 catch 문에서 잡히게 됩니다. catch문은 모든 Exception을 일괄적으로 잡거나 혹은 특정 Exception을 선별하여 잡을 수 있습니다.

출처 : http://programmedlessons.org/java5/Notes/chap80/ch80_7.html

 

 

모든 Exception을 잡고 싶을 때는 catch { ... } 와 같이 하거나 catch (Exception ex) { ... } 처럼 모든 Exception의 베이스 클래스인 System.Exception을 잡으면 됩니다.

특정 Exception을 잡기 위해서는 해당 Exception Type을 catch하면 됩니다. 즉 Argument와 관련된 Exception을 잡고 싶으면,

catch (ArgumentException ex) { ... }

와 같이 잡으면 됩니다.

catch 블럭은 하나 혹은 여러 개 일 수 있습니다. 여러 catch를 사용하는 이유는 각 Exception 유형에 따라 서로 다른 에러 핸들링을 하기 위함입니다.

finally는 Exception이 발생했던 발행하지 않았던 상관없이 마지막에 반드시 실행되는 블럭입니다.

예를 들어, try 블럭에서 SQL Connection 객체를 만든 경우, finally 블럭에서 Connection 객체의 Close() 메서드를 호출하면, 에러 발생 여부와 상관없이 항상 Connection 객체가 닫히게 됩니다.

위 코드에서 try 구문안에서 ArgumentException이 발생할 경우 해당 catch 문으로 빠졌다가 finally 구문으로 갈 것이며 Exception이 발생하지 않는다면 try 구문 실행 후 바로 finally 구문으로 갈 것입니다.

출처 : http://icodeguru.com/dotnet/beginning-csharp-objects/8880final/LiB0133.html

throw

try 블럭에서 Exception이 발생하였는데 이를 catch 문에서 잡았다면, Exception은 이미 처리된 것으로 간주됩니다.

때때로 catch문에서 기존의 Exception을 다시 상위 호출자로 보내고 싶을 때가 있는데, 이때 throw 를 사용합니다.

throw 문은 아래와 같이 크게 3가지로 구별됩니다.

(1) throw 문 다음에 catch에서 전달받은 Exception 객체를 쓰는 경우

- 이는 throw ex; 와 같이 catch(Exception ex) 에서 전달받은 Argument ex를 사용하는 경우입니다.

이러한 throw 방식은 ex에 담긴 예외 정보를 보전하지만, Stack Trace 정보를 다시 리셋하기 때문에 throw문 이전의 콜스택(Call Stack) 정보를 유실하게 됩니다. 따라서 일반적으로 이러한 방식은 사용하지 않는 것이 좋습니다.

(2) throw 문 다음에 새 Exception 객체를 생성해서 전달하는 경우

- 새로운 Exception 객체를 만들어 던지기 위해서는 throw new MyException(); 와 같이 C#의 new를 사용하여 새로운 Exception 객체를 만든 후, 이 객체를 throw 하면 됩니다. 이는 catch에서 잡은 Exception을 Wrapping하여 새로운 Exception을 전달할 때 사용하는데, 잘못 사용하면(InnerException을 포함하지 않으면) 기존 Exception 정보를 잃을 수 있습니다.

따라서, 이러한 방식을 사용하여 새로운 Exception 객체를 만들 때는 catch에서 얻은 Exception 객체를 새 객체의 InnerException에 포함시켜 에러 정보를 보전하는 것이 좋습니다.

예를 들어, throw new MyException(msg, ex); 와 같이 catch에서 전달받은 ex를 InnerException으로 전달하는 것이 좋습니다. InnerException의 StackTrace 속성은 어느 라인에서 에러가 발생하는지를 알려주는데, 이는 에러가 다른 메서드에서 발생했을 때는 물론 동일 메서드에서 발생했다 하더라도 정확히 어떤 라인에서 에러가 발생했는지 알게 해줍니다.

(3) throw 문 다음에 아무것도 없는 경우

throw; 와 같이 뒤에 어떠한 Exception 객체 없이 그냥 throw문만을 사용할 수 있는데, 이는 catch문에서 잡힌 Exception을 그대로 상위 호출 함수에게 전달하는 일(rethrow)을 합니다. 즉, 에러를 발생시킨 콜스택 정보를 그대로 상위 호출 함수에 전달하려면 이렇게 throw; 를 호출하면 됩니다.

한가지 주목할 점은, throw; 는 에러가 다른 메서드에서 발생했을 때는 그 에러가 발생한 다른 메서드의 위치를 포함하지만, 만약 throw문과 동일한 메서드에서 에러가 발생했다면 동일 메서드의 어느 라인에서 에러가 발생했는지는 포함하지 않습니다.

http://www.csharpstudy.com/CSharp/CSharp-exception.aspx

 

C# 예외 처리 - C# 프로그래밍 배우기 (Learn C# Programming)

C# Exception 예외 처리 C#을 포함한 모든 .NET 프로그래밍 언어는 .NET Framework의 Exception 메카니즘에 따라 Exception을 처리한다. .NET의 System.Exception은 모든 Exception의 Base 클래스이며, 예외 처리는 이 Except

www.csharpstudy.com

 

http://icodeguru.com/dotnet/beginning-csharp-objects/8880final/LiB0133.html

 

C# Exception Handling

Another useful Exception class property is the Source property, used to determine the application or object that triggered the exception. For a complete listing of methods/properties available for each of the derived exception types, please consult the FCL

icodeguru.com

 

 

[출처] [C#] Exception 예외 처리 (try-catch-finally, throw)|작성자