전체 페이지뷰

2016년 12월 27일 화요일

C# Exception Handling

프로그램 실행 중 비정상적인 상황이 발생하면 CLR에게 던져진  에러메세지를 받아 출력하고 프로그램은 강제 종료됩니다. 이런 상황을 처리하는 방법에 대해 알아보도록 하겠습니다.  그런데 왜 에러가 안 나게 하는 법을 배우지 않고 에러를 처리하는 법을 배우는거냐고요? 가장 훌륭한 프로그래머들이 모여 가장 최첨단의 프로그램을 만드는 Microsoft에서 만든 윈도우도 에러가 나서 죽거나 멈추거나 하지 않습니까?

가장 나쁜 경우는 예외가 발생했을 때 처리되지 못하고 이유도 모른 채 죽어버리는 거죠.
그런 경우를 막는 것이 이번 배움의 목표 되겠습니다.


System.Exception 클래스


C#에서 발생하는 모든 예외(exception)는 이 클래스 내부에 정의되어 있습니다(참고).
그 얘기는 C#에서 발생하는 모든 예외의 유일한 부모 클래스가 System.Exception이라는 말입니다.  그렇다고 해서 모든 예외를 이 클래스만 이용해서 다 받아내는 방식으로 처리하면 곤란합니다. 프로그래머가 일어날거라 예상치 않은 문제까지 다 받아낼수 있는 클래스이므로 상황에 따른 적절한 대처를 하기 어려울 수 있기 때문입니다.

try~catch


예외가 발생한 코드에서 예외가 발생하고, 그 예외상황을 담은 객체를 Main() 함수로 던져지며, Main내에 처리할 준비가 되어 있지 않다면 그 예외는  다시 CLR로 던져집니다. 그렇게 되면 처리되지 않은 예외 상황으로서 프로그램이 강제 종료 되는 거죠.

CLR로 던져지기 전에 그 예외를 try~catch 문으로 받아 처리하면 컨트롤 되지 않은 예외가 발생하는 것을 막을 수 있습니다.

try
{   //실행하려는 코드;}
catch (예외객체1)
{    //처리;   }
catch (예외객체2)
{    //처리;    }

의 문법을 사용합니다.

using System;
namespace TryCatch
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                int a = int.Parse(Console.ReadLine());
            }
            catch(FormatException e)
            {
                Console.WriteLine("예외 발생: {0}", e.Message);
            }
            Console.WriteLine("종료합니다.");            
        }    
    }
}
cs

결과)
g
예외 발생: 입력 문자열의 형식이 잘못되었습니다.
종료합니다.

숫자를 처리하려는 코드였는데 사용자가 문자를 입력했습니다. 물론 아예 문자가 입력되는 것을 막아야겠지만 예를 들기 위한 것있음을 감안해 주세요.


throw

지금까지 계속 예외를 "던진다"라는 표현을 써 왔습니다. 그것이 바로 "throw"입니다.
코드 내에서 예외가 throw되면 CLR은 그 예외를 처리하는 catch문을 검색합니다.

try 
{
    // ....
    throw new Execption("예외 발생");
}
catch(Exception e)
{
    Console.WriteLine(e.Message);
}

와 같은 형식입니다. 위의 throw문으로 던져진  예외는 아래  catch 문에서 받아집니다.

예제를 보겠습니다.

using System;
namespace Throw
    class Program
    {
        static void SimpleMethod(int arg)
        {
            if (arg < 10)
                Console.WriteLine("args = {0}", arg);
            else
                throw new Exception("arg가 10보다 큼");
        }
        static void Main(string[] args)
        {
            try
            {
                SimpleMethod(1);
                SimpleMethod(3);
                SimpleMethod(5);
                SimpleMethod(10);
                SimpleMethod(13);
            }
            catch(Exception e)
            {
                Console.WriteLine("예외 발생: {0}", e.Message);
            }                       
        }    
    }
}
cs



try~catch~finally

try블럭에서 예외가 발생하면 바로 catch로 실행이 넘어갑니다. 그런데 만약 try절에서 파일 열기를 실행한 이후 예외가 발생하여 파일을 닫지 못하고 넘어간다면 문제가 생길 수 있습니다. 그런 중요한 코드가 실행되지 않고 넘어가는 것을 방지하기 위하여 finally절에 작성된 내용은 어떤 경우에도 실행되도록 합니다.

try
{
    file.ReadBlock(buffer, index, buffer.Length);
}
catch (System.IO.IOException e)
{
    Console.WriteLine("Error reading from {0}. Message = {1}", path, e.Message);
}
            
finally
{
    if (file != null)
    {
        file.Close();
    }
}
cs

댓글 없음:

댓글 쓰기