비트를 쪼개는 개발자

allen321@naver.com

C#

C# - 예외 처리 (try ~ catch)

MozarTnT 2024. 9. 19. 11:29
728x90
반응형

 

 

 

 

 

예외 처리(Exception Handling)란?

 

  • 예외 처리란 프로그램 실행 중에 발생할 수 있는 의도치 않은 오류 상황이나 프로세스가 발생할 때 이를 관리하고 제어하기 위한 일종의 메커니즘이다.

 

  • "예외"라는 것은 내가 의도한 프로그램의 정상적인 흐름을 방해하는 요소이며 예외 처리를 해 놓으면 이를 통해 오류를 적절하게 처리할 수 있다.

 

  • TryCatch, 그리고 Finally 키워드는 C# 뿐만 아니라 자바와 파이썬 등 여러 언어에서 사용하는 예외 처리용 키워드다.

 

 

 

Catch에서 Exception 클래스를 상속받거나 사용 가능한 예외 타입 목록

 

- 일반적인 예외

 

  • Exception: 모든 예외를 포괄적으로 처리하는 기본 클래스, 모든 예외를 잡을 때 사용한다.
  • SystemException: CLR(Common Language Runtime)에서 발생하는 예외의 기본 클래스.

 

- 구체적인 예외

 

  • FormatException: 입력된 데이터가 예상된 형식과 맞지 않을 때 발생
  • OverflowException: 산술 연산이나 형식 변환 중에 오버플로가 발생했을 때 발생
  • NullReferenceException: null 객체의 멤버에 접근하려고 시도할 때 발생
  • IndexOutOfRangeException: 배열이나 컬렉션의 잘못된 인덱스에 접근하려고 할 때 발생
  • InvalidOperationException: 메서드 호출이 현재 객체 상태에서 허용되지 않는 경우 발생
  • ArgumentException: 메서드에 전달된 인수가 유효하지 않을 때 발생
  • ArgumentNullException: 메서드에 null 인수를 전달할 수 없는데 전달된 경우 발생
  • FileNotFoundException: 파일이 존재하지 않을 때 발생
  • IOException: 입출력 작업 중에 발생하는 일반적인 예외
  • SqlException: 데이터베이스 관련 작업 중에 발생하는 예외
  • WebException: 네트워크 요청 중에 발생하는 예외

 

 

 

 

코드 예시

 

try
{
    Console.WriteLine("숫자를 입력하세요:");
    int number = int.Parse(Console.ReadLine());
    Console.WriteLine("입력한 숫자: " + number);
}
catch (FormatException ex)
{
    Console.WriteLine("숫자가 아닙니다: " + ex.Message);
}
catch (Exception ex)
{
    Console.WriteLine("예기치 못한 오류 발생: " + ex.Message);
}
finally
{
    Console.WriteLine("프로그램을 실행을 종료합니다.");
}

 

Try 블록

 

  • Try 블록의 역할은 예외가 발생 할 가능성이 있는 코드를 담아두는 공간이다.
  • 이 블록 내에서 예외가 발생하면 그 즉시 catch 블록으로 넘어간다.
  • 위 코드 예시에서는 예외가 발생한 경우에 따라 두개의 catch 블록 중 하나로 넘어간다.
  • Console.ReadLine() 으로 받아온 변수가 숫자가 아닐 경우에는 (FormatException ex)를 매개 변수로 가진 catch 로 넘어간다.
  • 이외의 모든 예외처리 상황은 아래의 catch로 넘어간다.

 

 

Catch 블록

 

  • catch 블록은 try 블록에서 발생한 예외를 catch 블록으로 넘어와서 처리한다.
  • 예외의 종류에 따라서 여러개의 catch 블록을 사용할 수 있다. 

 

Finally 블록

 

  • Finally 블록은 예외 발생 여부와 관계없이 항상 실행된다.
  • Finally 블록은 try 도중 return, throw문을 만나도 반드시 실행되기 때문에 반드시 유의해야 한다.
  • Finally 블록 도중 예외가 발생한다면 이는 처리되지 않은 예외로 남게된다.
  • Finally 블록 안에서도 또 다른 try~catch를 사용할 수 있다.

 

코드 실행 예시

 

 

숫자를 넣으면 catch 구문으로 넘어가지 않고 try와 finally만 실행되며 종료된다.

 

 

 

숫자가 아닌 다른 값을 넣으면 유효한 변수가 아니라며 첫번째 catch로 넘어간다.

 

 

 

int의 크기를 초과하는 숫자를 넣으면 예기치 못한 오류가 발생했다며 두번째 catch로 넘어간다.

 


 

 

Throw 

 

  • Throw는 예외를 의도적으로 발생시키거나 상위 메서드에 예외를 던질 때 사용된다.
  • 예외가 발생한 위치에 대한 정보를 유지한 채로 상위 메서드로 전파하기 때문에 상위 메서드에서 예외를 다시 처리할 수 있다.
  • 특정 예외에 대해서 부분적인 처리만 하고 상위로 넘겨주기 좋은 방법이다.
  • 예외의 원인 분석 파악하기에 아주 좋은 키워드다.

 

public static void Main()
{
    try
    {
        InputNumber();
    }
    catch (FormatException ex)
    {
        Console.WriteLine("Main에서 예외 처리: 유효한 숫자가 입력되지 않았습니다. " + ex.Message);
    }
    catch (Exception ex)
    {
        Console.WriteLine("Main에서 예기치 못한 오류 처리: " + ex.Message);
    }
}

public static void InputNumber()
{
    try
    {
        Console.WriteLine("숫자를 입력하세요:");
        int number = int.Parse(Console.ReadLine());
        Console.WriteLine("입력한 숫자: " + number);
    }
    catch (FormatException ex)
    {
        Console.WriteLine("숫자가 아닙니다: " + ex.Message);
        throw; // 예외를 다시 던짐
    }
    catch (Exception ex)
    {
        Console.WriteLine("예기치 못한 오류 발생: " + ex.Message);
    }
    finally
    {
        Console.WriteLine("Input Number에서 프로그램 실행을 종료합니다.");
    }
}

 

 

위 코드의 흐름을 살펴보자.

 

InputNumber()가 실행 중이며 InputNumber() 내부에서 try와 catch를 사용중이다.

 

다만 숫자가 아닌 예외가 발생하면 throw 키워드를 사용하여 이 예외에 대한 정보를 상위 Main 메서드로 넘긴다.

 

Main에서는 해당 예외에 대한 정보를 가져가며 Main의 catch부분에서 하위 예외에 대한 정보를 가져갈 수 있게 된다.

 

 

 

 

 

예외를 발생시키는 Throw 예시

 

 

public void ValidateAge(int age)
{
    if (age < 0 || age > 120)
    {
        throw new ArgumentOutOfRangeException("age", "나이는 0에서 120 사이로만 입력하세요.");
    }
    Console.WriteLine("입력된 나이: " + age);
}

try
{
    ValidateAge(-5);
}
catch (ArgumentOutOfRangeException ex)
{
    Console.WriteLine("예외 발생: " + ex.Message);
}

 

 

 

위 예시에서는 try에서 실행하는 함수의 매개변수가 0에서 120 사이가 아닌 경우에 throw문을 통해 예외를 발생시켜 준다.

 

구체적인 예외처리에서는 규격에 맞지 않는다거나 Null에 참조하려고 하는 아주 확실한 예외가 아니라면 처리하기 까다로운 부분이 있는데, throw 키워드를 통해 예외를 발생시켜 버리면 이런 사용자가 원하는 예외를 처리하기에 적합하다.

728x90
반응형