본문 바로가기
C#/이론

[예제로 배우는 C# 프로그래밍] 예외 처리

by 단월໒꒱ 2022. 7. 6.

 

C# 예외 처리

 

 

예외 처리

 

  C#을 포함한 모든 .NET 프로그래밍 언어는 .NET Framework의 Exception 메커니즘에 따라 예외를 처리한다. .NET의 System.Exception은 모든 Exception의 Base 클래스이며, 예외 처리는 이 Exception 객체를 기본으로 처리하게 된다.

 

  만약 예외가 발생했는데 이를 프로그램 내에서 처리하지 않으면 이를 Unhandled Exception이라 부르고, 프로그램은 Crash하여 종료된다.

 

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

 

 

try
{
   // 실행하고자 하는 문장들
   DoSomething();
}
catch (Exception ex)
{
   // 에러 처리/로깅 등
   Log(ex);
   throw;
}

 

 

 

try - catch - finally

 

  try 블럭은 실제 실행하고 싶은 프로그램 명령문들을 갖는 블럭이다. 만약 여기서 어떤 에러가 발생한다면, 이는 catch문에서 잡히게 된다.

  catch문은 모든 Exception을 일괄적으로 잡거나 혹은 특정 Exception을 선별하여 잡을 수 있다.

 

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

  특정 Exception을 잡기 위해서는 해당 Exception Type을 catch하면 된다. 즉, Argument와 관련된 Exceptionㅇ르 잡고 싶으면, catch (ArgumentException ex) { ... }와 같이 잡게 된다.

 

  catch 블럭은 하나 또는 여러개일 수 있다.

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

 

 

try
{
   //실행 문장들
}
catch (ArgumentException ex)
{
   // Argument 예외처리
}
catch (AccessViolationException ex)
{
   // AccessViolation 예외처리
}
finally
{
   // 마지막으로 실행하는 문장들
}

 

 

 

throw

 

  try 블럭에서 Exception이 발생했는데 이를 catch 문에서 잡았다면, Exception은 이미 처리된 것으로 간주된다. 종종 catch문에서 기존의 Exception을 다시 상위 호출자로 보내고 싶을 때가 있는데 이때 throw를 사용한다.

 

 

try
{
    // 실행 문장들
    Step1();
    Step2();
    Step3();
}
catch(IndexOutOfRangeException ex)
{
    // 새로운 Exception 생성하여 throw
    throw new MyException("Invalid index", ex);
}
catch(FileNotFoundException ex)
{    
    bool success = Log(ex);
    if (!success)
    {
        // 기존 Exception을 throw
        throw ex;
    }
}
catch(Exception ex)
{    
    Log(ex);
    // 발생된 Exception을 그대로 호출자에 전달
    throw;
}

 

 

 

예제

 

  다음 예제는 SQL Server에 연결하여 데이터베이스 내의 테이블, 뷰 등의 SQL Objects 수를 가져온 후 이를 화면에 뿌리는 코드이다.

 

 

string connStr = "Data Source=(local);Integrated Security=true;";
string sql = "SELECT COUNT(1) FROM sys.objects";
SqlConnection conn = null; 
try
{
    conn = new SqlConnection(connStr);
    conn.Open();
    SqlCommand cmd = new SqlCommand(sql, conn);
    object count = cmd.ExecuteScalar();
    Console.WriteLine(count);                
}
catch (SqlException ex)
{
    Console.WriteLine(ex.Message);
}
finally
{
    if (conn != null && 
        conn.State == System.Data.ConnectionState.Open)
    {
        conn.Close();
    }
}

 

 

  SQLException 타입의 에러가 발생하면 catch 블럭에서 잡아 에러 메세지만 콘솔에 표시하고 Exception을 삼키게 된다. 마지막의 finally 블럭은 SqlConnection의 Close() 메서드를 실행하여 Connection을 닫는다. 에러가 발생하지 않더라도 finally 블럭은 실행되며, 이로 인하여 SQL Connection은 항상 닫히게 된다.

 

 

 

댓글