프로그램을 실행하다보면 여러가지 이유로 에러가 발생할 수 있다.

이럴 경우, 보통 프로그램은 멈추거나 꺼지거나 하게되는데 이런 일을 막기위한 것이 바로 예외처리다.

 

예외처리에는 여러가지 방법이 있는데 다음과 같다.

 

try-catch

try - catch문은 대강 다음과 같이 사용한다.

 

try{
	//원하는 내용 입력
}
catch (FormatException e){
	//원하는 내용 입력
}

try의 {} 내에는 시험할 내용을 입력한다.

catch는 try의 {} 안에서 에러가 발생할 경우, catch로 넘어오게 한다.

 

예를 들어서

try{
	1번코드
	2번코드
	3번코드
	4번코드
}
catch (FormatException e){
	5번코드
}

이 코드는 1번코드 -> 2번코드 -> 3번코드... 순서대로 실행된다.

그런데 이 코드에서 만약 2번 코드를 실행하던 중 에러가 발생할 경우 바로 catch문인 5번코드로 넘어가게 된다.

 

만약 어떤 코드에서도 에러가 발생하지 않았다면? 4번코드까지 실행하고 5번코드는 실행되지 않는다.

 

여기서 catch의 FormatException e 는 발생한 에러를 말한다.

예를 들어, 에러 발생시, 에러 메시지를 출력한다면

try{
}
catch (Exception e){
	Console.WriteLine(e.Message);
}

이런 식으로 입력하면 된다.

 

Exception

에러는 많은 종류를 가지고 있으며 그 종류와 용도는 다음과 같다.

ArgumentException
메서드에 전달 되는 null이 아닌 인수가 잘못되었다.

ArgumentNullException
메서드에 전달 되는 인수가 null이다.
ArgumentOutOfRangeException
인수가 유효한 값 범위를 벗어났다.
DirectoryNotFoundException
디렉터리 경로 일부가 잘못되었다.
DivideByZeroException
0으로 나누었다.
DriveNotFoundException
드라이브가 없거나 사용할 수 없다.
Exception
모든 종류의 예외를 처리할 수 있다.
FileNotFoundException
파일이 없다.
FormatException
문자열에서 변환할 수 있는 적절 한 형식이 아니다.
IndexOutOfRangeException
인덱스가 배열 또는 컬렉션의 범위를 벗어났다.
InvalidOperationException
개체의 현재 상태에서 메서드 호출을 사용할 수 없다.
KeyNotFoundException
컬렉션의 멤버에 액세스 하는 데 지정 된 키를 찾을 수 없다.
NotImplementedException
메서드 또는 작업이 구현 되지 않았다.
NotSupportedException
메서드 또는 작업이 지원 되지 않는다.
ObjectDisposedException
삭제 된 개체에 대한 작업을 수행했다.
OverflowException
산술, 캐스팅 또는 변환 작업을 수행 하면 오버플로가 발생한다.
OverflowException
작업 결과가 대상 데이터 형식의 범위를 벗어났다.
PathTooLongException
경로 또는 파일 이름이 시스템에서 정의한 최대 길이를 초과한다.
PlatformNotSupportedException
현재 플랫폼에서 작업이 지원 되지 않는다.
RankException
차원 수가 잘못되었다.
TimeoutException
작업에 할당 된 시간 간격이 만료 되었다.
UriFormatException
잘못 된 URI (Uniform Resource Identifier)가 사용 되었다.

 

여기서 가장 많이, 대중적으로 사용하는 키워드가 바로 Exception 이다.

 

또한 이 exception의 하위 키워드들은 모두 exception의 상속을 받은 서브 클래스다.

때문에 아래처럼 사용은 불가능하다.

try {
}
catch (Exception e)
{
}
catch (OverflowException e)
{
}

이미 가장 큰 개념인 Excepton에서 모든 에러를 검출했기 때문에 두번째 catch문은 에러가 난다.

때문에 아래와 같이 사용해야 한다.

try {
}
catch (OverflowException e)
{
}
catch (Exception e)
{
}

작은 부분을 먼저 검출하고, 그 다음 나머지를 검출한다.

 

사실 Exception 만 알아도 왠만한건 다 커버가 된다.

 

try-catch-finally

finally는 try구문을 실행하던 중 에러가 발생하든 하지 않든 실행하는 부분이다.

즉 에러가 발생하지 않아도 실행하고 에러가 발생해도 실행하는 부분이다.

try를 쓸 때는 catch가 필수이지만 finally는 필수가 아니다.

static void ThrowFunc(int data) {
    if(data > 0) {
        Console.WriteLine("ThrowFunc data: " + data);
    }
    else {
        throw new Exception("data에 0이 입력되었습니다.");
    }
}

static void Main(string[] args) {
    try {
        ThrowFunc(10);
        ThrowFunc(100);
    }
    catch(Exception e) {
        Console.WriteLine(e.Message);
    }
    finally {
        Console.WriteLine("  finally 무조건 실행  \n");
    }
}

이 코드를 실행할 경우, try에서 에러가 발생하든 하지 않든 상관없이 finally는 무조건 실행된다.

에러를 일으키고 싶다면 ThrowFunc에서 파라미터 값을 10이 아닌 0이나 그 이하값을 주면 된다.

 

throw

try-catch가 실행 중 에러 검출이라면 throw는 원하는 타이밍에 에러를 낸다고 볼 수 있다.

 

if(data > 0) {
    Console.WriteLine("정상실행");
}
else {
    throw new Exception("에러발생");
}

위 구문에서, data가 0보다 크면 정상실행되지만 아닐 경우, throw를 통해서 에러를 반환한다.

참고로 이때 키워드 또한 Exception 말고도 위에서 표로 작성했던 다른 하위 Exception을 사용할 수도 있다.

 

직접만드는 예외 클래스

앞서 말했듯이 exception은 많은 하위 클래스를 가지고 있다.

마찬가지로, 임의로 클래스를 가져와 상속을 해주는 형태로 새로운 예외클래스를 만들 수 있다.

 

class MyException : ApplicationException
{
    public int Num { get; set; }
    public MyException():base() {
    }
    public MyException(int a) {
        Num = a;
    }

    public override string ToString() {
        return "Num: " + Num;
    }
}

 

ApplicationException을 상속받아 나만의 애러를 만들었다.
ApplicationException의 base를 상속 받고 정수를 받는데, MyException이 호출되면  Num값이 에러메시지로 출력된다.

 

 

 

+ Recent posts