나만의 작은 도서관

[C#] 문법 정리 #10. 예외 처리 본문

Unity/문법 및 메소드(System)

[C#] 문법 정리 #10. 예외 처리

pledge24 2024. 11. 23. 20:46

예외 처리(Exception Handling)

예외 처리(Exception Handling)는 프로그램 실행 중 발생할 수 있는 오류를 감지하고 이를 처리하여 프로그램의 비정상 종료를 방지하는 구조화된 방법을 제공한다. C#에서는 try, catch, finally 블록과 throw 키워드를 사용하여 예외를 처리한다.

 

예외 처리를 하면 좋은 이유

컴파일 시점에서 발생하는 오류는 코드를 수정하여 해결하면 그만이지만, 런타임 중에 발생하는 오류는 도중에 해결할 수 없다. 이렇게 발생한 오류가 사소한 오류라면 괜찮겠지만 치명적인 오류(프로그램을 멈추게 하는 것과 같이)라면 큰 문제가 된다. 예외처리는 이러한 오류가 발생했을 때 적절히 처리하고 프로그램의 실행을 계속할 수 있도록 한다.

 

이처럼, 예외 처리는 예외 상황에 대비하여 프로그램을 안정적으로 유지하는 데 도움을 준다.

 

기본 구조

  • try: 예외가 발생할 가능성이 있는 코드를 감싸는 블록. 예외 발생 시, 해당 예외를 처리하는 catch 블록으로 이동한다.
  • catch: try 블록에서 발생한 예외를 처리하는 블록. 예외 타입(ExceptionType)을 지정하여 특정 예외만 처리하거나, Exception 클래스로 모든 예외를 처리할 수 있다.
  • finally: 예외 발생 여부와 상관없이 반드시 실행되는 블록. 자원 정리, 파일 닫기, 연결 해제 등에 주로 사용한다.
  • throw: 예외를 발생시키거나, 발생한 예외를 다시 호출자에게 전달하는 키워드. 사용자 정의 예외(Custom Exception)또한 발생시킬 수 있다.
try
{
    // 예외가 발생할 수 있는 코드
}
catch (ExceptionType ex)
{
    // 예외를 처리하는 코드
}
finally
{
    // 예외 발생 여부와 상관없이 실행되는 코드 (선택적)
}

 

 

예외 처리 예제

예외 타입은 상속 관계에 있는 경우 상위 예외 타입의 catch 블록이 먼저 실행된다.

try
{
    int a = 10;
    int b = 0;
    int result = a / b; // ZeroDivisionException 발생
}
catch (DivideByZeroException ex)
{
    Console.WriteLine($"Error: {ex.Message}");
}
finally
{
    Console.WriteLine("예외 처리 완료.");
}

 

catch 블록 추가 예제

catch문은 catch문을 추가로 연결하여 여러 종류의 예외를 따로 처리할 수 있으며, if문 처럼 2중, 3중으로 중첩할 수 있다.

// 다중 catch 블록 예제(실행 순서는 위에서부터)
try
{
    int[] numbers = { 1, 2, 3 };
    Console.WriteLine(numbers[5]); // IndexOutOfRangeException 발생
}
catch (IndexOutOfRangeException ex) // IndexOutOfRangeException 타입의 예외 처리
{
    Console.WriteLine("인덱스가 범위를 벗어났습니다.");
}
catch (Exception ex)	// 그 외 예외 처리
{
    Console.WriteLine($"알 수 없는 예외 발생: {ex.Message}");
}

 

 

throw 추가 예제

예외를 처리한 후 호출자에게 다시 예외를 전달하고 싶을 때 throw를 사용한다.

try
{
    try
    {
        throw new InvalidOperationException("내부 예외 발생");
    }
    catch (InvalidOperationException ex)
    {
        Console.WriteLine($"내부에서 처리: {ex.Message}");
        throw; // 예외를 다시 던짐
    }
}
catch (Exception ex)
{
    Console.WriteLine($"외부에서 처리: {ex.Message}");
}

// [출력 결과]
// 내부에서 처리: 내부 예외 발생
// 외부에서 처리: 내부 예외 발생

 

 

when 키워드

C#은 catch 블록에 when을 추가해 catch 블록 진입 조건을 걸 수 있다. (일종의 필터 역할을 한다고 보면된다.)

try
{
    int value = -1;
    if (value < 0)
        throw new ArgumentException("값은 음수가 될 수 없습니다.");
}
// 예외 메세지에 "음수"가 포함되어 있는 경우만 진입
catch (ArgumentException ex) when (ex.Message.Contains("음수"))	
{
    Console.WriteLine("특정 예외 처리: 음수 에러");
}

 

 

사용자 정의 예외 처리

사용자 정의 예외를 추가하고 싶다면 Exception을 상속한 자식 클래스로 생성하면 된다.

public class NegativeNumberException : Exception
{
    public NegativeNumberException(string message) : base(message)
    {
    }
}

try
{
    int number = -10;
    if (number < 0)
    {
        throw new NegativeNumberException("음수는 처리할 수 없습니다.");
    }
}
catch (NegativeNumberException ex)
{
    Console.WriteLine(ex.Message);
}
catch (Exception ex)
{
    Console.WriteLine("예외가 발생했습니다: " + ex.Message);
}