C# Exception VS Return Code

조회수 2499회

질문 1

    public class foo { }
    public foo SomeFooNULL()
    {
        var newFoo = new foo();
        if(null == newFoo)
        {
            return null;
        }

        return newFoo;
    }

    public foo SomeFooException()
    {
        var newFoo = new foo();
        if (null == newFoo)
        {
            throw new NullReferenceException();
        }

        return newFoo;
    }

기존에 접하던 C, C++ 의 경우 보통 SomeFooNULL 함수와 같은 방식의 리턴을 하고 호출측에서 널체크 같은 방어 코드를 작성하는 식으로 하는데 최근 C#을 접하다 보니 C#에서는 아래 같은 방식으로 작성된 예제 코드들도 볼수 있습니다. 위와 같은 코드가 있을때 어떤 방식이 C#에서 권장하는 방법인지 혹은 어떤 방식으로 많이들 사용하는지 궁금합니다.

질문 2

public enum FOO_RESULT
    {
        OK = 0,
        ERROR = 1,
        FOO = 2,
        BAR = 3
    }

    public FOO_RESULT DoSomeEnum()
    {
        if(true /* 임의 에러 체크1*/)
            return FOO_RESULT.ERROR;

        if (true /* 임의 에러 체크2*/)
            return FOO_RESULT.FOO;

        /* 임의의 작업 */


        return FOO_RESULT.OK;
    }


    [Serializable]
    public class MyException : Exception
    {
        public MyException(string message) : base(message) { }
    }

    public void DoSomeException()
    {
        if (true /* 임의 에러 체크1*/)
            throw new MyException("ERROR");

        if (true /* 임의 에러 체크2*/)
            throw new MyException("FOO");

        /* 임의의 작업 */
    }

위 질문의 연장선상으로 보통 전통적인 방법은 위의 DoSomeEnum 함수처럼 리턴값이 단순 Boolean 이 아닌 여러개인 경우 Enum을 정의하고 그것을 리턴 하는 방식으로 호출자에게 돌려주어 처리하게 하는데 C#에서는 아래 같이 UserException을 직접 정의하고 예외를 바로 던지는 경우의 예제 코드들도 볼수 있는데 어떤 방식이 권장되는지 궁금합니다.

추가로 C++에서의 Exception은 매우 느린편인데 c#의 Exception의 경우 성능저하가 어느정도인지 우려할 수준인가도 궁금합니다. 질문을 하다보니 매우 길어지게 되었는데 한수 부탁드립니다.

2 답변

  • 좋아요

    4

    싫어요
    채택 취소하기

    error code와 exception은 각각 장/단이 있습니다.

    exception의 경우 아주 성능에 민감한 어플리케이션(DB 등 미들웨어) 성능상 분명히 손해가 있지만, 그렇지 않은 경우에는 크게 문제가 되지는 않습니다.

    error code를 사용했다면 스택이 깊어진 상태에서 상단으로 에러를 전달하기가 매우 어렵습니다. (한 단계씩 매번 상위로 에러 코드를 전달해야 합니다, 이는 호출자 측면에서 처리에 어려움이 됩니다)

    Exception을 사용하면 Error code로는 얻지 못하는 stack jump를 할 수 있습니다. 이를 잘 활용하면 쉽게 에러 로그나 기타 예외 처리를 한 곳에서 모아서 처리 할 수 있습니다.

    때문에 보통 웹 프레임워크 등을 보면 사용자 요청이 오는 엔트리 포인트를 Try / Catch로 잡아서 일관된 예외/에러 처리를 합니다.

    참고로, 예외 자체는 크게 느리지 않습니다.

    예외가 발생된 스택이 깊은 경우에 너무 높은 곳에서 예외를 처리하게 될 때 성능이 문제가 되는데(스택 정보를 말아올리기 때문에), 이 부분이 심각하게 문제가 되는 경우 해당 동작을 재정의 해서 성능 저하를 막는 방법도 있습니다.

    물론 이 때에는 상세한 스택 정보는 잃어버리게 되지만 컨트롤 플로우는 정확하게 유지됩니다.

    • (•́ ✖ •̀)
      알 수 없는 사용자
    • 아 그렇군요 그다지 성능에 민감한 부분이 아니고 스텍 트레이스 나 코드의 복잡성을 생각하면 익셉션쪽이 장점이 더 클수가 있겠네요. 답변 감사합니다. Sang-Woo Park 2016.2.19 12:30
  • 상황에 따라 다를 수 있는데요. throw는 오류라고 판단 될때만 사용하시면 될 듯 합니다.

    1. foo 객체가 할당이 안되서 null인 상황을 오류라고 판단하시면 trow 하시고, 할당안되는 상황이 정상일 수도 있으면 null또는 빈 객체를 리턴하시면 될 듯합니다.
    2. throw 를 자주 사용하면 C#도 성능에 안 좋습니다. 특수한 상황이 아니라면 enum을 사용하시면 될 듯합니다.

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)