- 예외:
프로그래머가 생각한 시나리오에서 벗어나는 사건.- 예외처리:
프로그램의 오류나 다운으로 이어지지 않도록 적절하게 처리하는 것
ex) ㄴ 배열 요소가 3개 밖에 없는데, 4번째 요소까지 접근(i < 5) 했기 때문에 예외 발생!!
-> 이 메시지는 CLR(가비지 컬렉터)가 출력한 것이다. 잘못된 인덱스를 통해 배열의 요소에 접근하려 들면 배열 객체가 이 문제에 대한 상세 정보를 IndexOutOfRangeException의 객체에 담은 후 Main()메소드에 던지는데, 위 예시처럼 Main()이 예외를 처리할 방도가 없다면 다시 CLR에 던진다. CLR이 '처리되지 않은 예외'를 받게 되면 예외 객체에 담긴 내용을 사용자에게 출력한 후 프로그램을 강제 종료시킨다.
try { 실행하려는 코드 } catch(Exception 변수명) { 예외가 발생했을 때의 처리 방법 }
이 클래스는 모든 예외의 조상 클래스이다. 위에서 사용한 IndexOutOfRangeException
클래스도 System.Exception
으로부터 파생됐다.
❓그러면 예외 형식에 따라 catch 절을 만들 필요 없이 System.Exception클래스만 사용하여 하나의 catch 절만 만들면 되지 않을까??
❌ 안된다!! 예외 상황에 따라 섬세한 예외 처리가 필요한 코드에서는 Exception만으로 대응이 어렵다.
System.Exception 형식은 프로그래머가 발생할 것으로 계산한 예외 말고도 다른 예외까지 받아내기 위해 사용하는 것이다!
ㄴ 만약 작성한 예외가 현재 코드가 아닌 상위 코드에서 처리해야 하는 문제였다면 이 코드는 예외를 처리하는 것이 아니라 버그를 만들고 있는 셈이기 때문이다;;
ㄴ 또한 System.Exception을 남용할 경우 처리하지 않아야 할 예외까지 처리하기 때문에 면밀히 검토해서 사용해야 한다.
throw문을 통해 던져진 예외 객체는 catch문을 통해 받는다.
try블록에서 코드를 실행하다가 예외가 던져지면 catch 절로 바로 넘어온다. 이때 try블록에서 자원 해제같은 중요한 코드를 미처 실행하지 못했다면 이는 곧 버그가 된다;; 이를 방지하기 위해 모든 catch 절에 중요한 코드를 작성하는 것은 매우 비효율적이다.
이때 사용하는 것이 finally절이다. finally절은 try코드가 다 실행된 후에도, 예외가 발생하여 catch가 실행된 후에도 '무조건' 실행되는 뒷정리 코드이다. (심지어, try절 안에 return문이나 throw문이 있더라도)
internal class Program
{
static void Main(string[] args)
{
try
{
Console.WriteLine("피제수를 입력하세요 : ");
String temp = Console.ReadLine();
int dividend = Convert.ToInt32(temp);
Console.WriteLine("제수를 입력하세요 : ");
temp = Console.ReadLine();
int divisor = Convert.ToInt32(temp);
Console.WriteLine($"{dividend}/{divisor} = {dividend / divisor}");
}
catch(FormatException e)
{
Console.WriteLine($"에러: {e.Message}");
}
catch(DivideByZeroException e)
{
Console.WriteLine($"에러: {e.Message}");
}
finally
{
Console.WriteLine("프로그램을 종료합니다.");
}
}
}
📄참고자료
<이것이 c#이다> 3판 - 박상현 지음 (한빛미디어)