[47] 사용자 지정 예외 클래스를 완벽하게 작성하라

다음 본문은 도서 이펙티브 C# (빌 와그너)에서 나오는 주제를 다룹니다.

 

 

예외 객체에 포함된 기존 오류 관련 정보를 훼손하지 않으면서도 저수준의 에러 내용을 응용프로그램 관점으로 재해석한 정보를 예외 객체에 포함시키고 싶을 수 있다. 이 경우 사용자 지정 예외 클래스를 만들 수 있다.

 

예외클래스의 목적

catch문을 작성할때 예외의 런타임 타입에 따라 서로 다른 작업을 수행하는게 일반적이다.

try
{
    Foo();
}
catch(MyFirstApplicationException e1)
{
    FixProblem(e1);
}
catch(AnotherApplicationException e2)
{
    ReportErrorAndContinue(e2);
}
catch(YetAnotherApplicationException e3)
{
    ReportErrorAndShutdown(e3);
}
catch(Exception e)
{
    ReportGenericError(e);
    throw;
}
finally
{
    CleanupResources();
}

따라서 특정 예외상황에서 특별한 처리를 하고 싶을때 예외 클래스를 만드는 것이 좋다. 다른 작업이나 복구 메커니즘으로 이어질 가능성이 있다면, 그 내용을 예외클래스에 담는 것이 도움이 된다.

 

2. 예외 클래스 만들기

1. 개별 예외 클래스의 고유한 책임을 명확하게 규정해야한다.

2. 모든 예외 클래스의 이름은 Exception으로 끝나야 한다.

3. System.Exception클래스나 혹은 더 적절한 클래스를 상속해서 구현해야한다.

 

새로운 예외클래스를 작성할 때는 반드시 4개의 생성자를 작성해야 한다.

// 기본 생성자
public Exception();
// 에러 메시지를 포함하는 생성자
public Exception(string);
// 에러 메시지와 내부 예외를 포함하는 생성자
public Exception(string, Exception);
// 입력 스트림을 이용하는 생성자
protected Exception(SerializationInfo, StreamingContext);

마지막 생성자는 예외 클래스가 serializae 가능해야 함을 의미하는 것이기도 하다.

[Serializable]
public class MyAssemblyException : Exception
{
    public MyAssemblyException() : base()
    {
    }
    
    public MyAssemblyException(string s) : base(s)
    {
    }
    
    public MyAssemblyException(string s, Exception e) : base(s, e)
    {
    }
    
    protected MyAssemblyException(SerializationInfo info,
        StreamingContext cxt) : base(info, cxt)
    {
    }
}

 

예외 변환

저수준의 예외에 대해서 보다 세부적인 상태 정보를 포함하는 고수준의 예외로 변경하는 작업

public double DoSomeWork()
{
    try
    {
        //...
        return ThirdPartyLibrary.ImportantRoutine();
    }
    catch(ThirdPartyException e)
    {
        var msg = $"Problem with {e.ToString()} using library";
        throw new DoingSomeWorkException(msg, e);
    }
}

 

결론

별도로 다루는 것이 적절하다고 생각되는 오류라면 독립된 예외클래스를 만들자.

 

 

댓글

Designed by JB FACTORY