switch statement-기본 사례에 도달 할 수없는 경우 처리


15

스위치 클래스를 사용하여 열거 형 (내 클래스가 소유 한)의 값을 처리하고 가능한 각 값에 대한 사례가있는 경우 "기본"사례를 처리하기 위해 코드를 추가 할 가치가 있습니까?

enum MyEnum
{
    MyFoo,
    MyBar,
    MyBat
}

MyEnum myEnum = GetMyEnum();
switch (myEnum)
{
    case MyFoo:
        DoFoo();
        break;
    case MyBar:
        DoBar();
        break;
    case MyBat:
        DoBat();
        break;
    default:
        Log("Unexpected value");
        throw new ArgumentException() 
}

나는이 코드에 도달 할 수 없기 때문에 (단위 테스트조차도) 생각하지 않습니다. 동료가 동의하지 않으며 이것이 MyEnum에 새 값이 추가되어 발생하는 예기치 않은 동작으로부터 우리를 보호한다고 생각합니다.

커뮤니티라고 뭐라고?


MyEnum이 널 입력 불가능 유형이라고 가정하십시오.
sd

3
"오늘"은 null이 아닙니다. 더 이상 코드를 유지하지 않을 경우 내일은 어떻습니까? 또는 "MyBiz"가 열거 형에 추가되었지만 사건은 아닌 경우는 어떻습니까? 유지 보수에 대한 Caleb의 의견은 매우 독창적입니다.

1
모든 경우를 다루지 않는 스위치가 있으면 치명적인 오류라고 컴파일러에 알려주십시오.

누군가가 잘못된 값을 캐스팅 MyEnum하여 스위치를 통해 전달하면 어떻게됩니까?
Mawg는 모니카

1
어떤 언어? Java 인 경우, Enum 안에 메소드를 배치하고이를 호출 (다형성)하여 switch명령문을 완전히 제거해야 합니다.
user949300

답변:


35

기본 대소 문자를 포함하더라도 코드 작동 방식은 변경되지 않지만 코드를 유지 관리하기 쉽게 만듭니다. 코드를 명확한 방식으로 중단 (메시지 기록 및 예외 발생)함으로써 회사가 내년 여름에 고용하여 몇 가지 기능을 추가하는 인턴에 큰 빨간색 화살표가 포함됩니다. 화살표는 "이봐 요, 당신! 예, 당신과 대화하고 있습니다! 열거 형에 다른 값을 추가하려면 여기에 사례를 추가하는 것이 좋습니다." 이러한 추가 노력으로 컴파일 된 프로그램에 몇 바이트를 추가 할 수 있습니다. 그러나 비생산적인 헤드 스크래칭 시간과 하루 사이에 누군가를 구할 수도 있습니다.


업데이트 : 위에서 설명한 상황, 즉 나중에 열거에 추가 된 값으로부터 보호하는 것은 컴파일러에 의해 포착 될 수 있습니다. 열거 형을 설정했지만 열거의 가능한 모든 값을 다루는 사례가없는 경우 Clang (및 gcc, 생각)은 기본적으로 경고를 발행합니다. 예를 들어 default스위치 에서 사례 를 제거 MyBaz하고 열거에 새 값 을 추가하면 다음과 같은 경고가 표시됩니다.

Enumeration value 'MyBaz' not handled in switch

컴파일러가 발견되지 않은 사례를 탐지하게하면 도달 할 수없는 default사례 가 크게 없어져 처음에 질문에 영향 을 미치게 됩니다.


2
좋아, 당신은 저를 설득했습니다 :) 나는 단지 내 코드 적용 번호의 찌그러짐을 받아 들여야합니다.
sd

@st 해당 코드를 테스트 할 이유가 없습니다. 열거 형에 추가 값으로 조건부로 컴파일하는 테스트 빌드를 수행 한 다음이를 사용하는 단위 테스트를 작성하십시오. 아마도 이상적이지는 않지만 일반적으로 도달 할 수없는 코드를 테스트해야하는 유일한 사례는 아닙니다.
Caleb

또는 열거 형 이외의 값을 열거 형 유형으로 캐스팅하여 사용합니다.
Mawg는 모니카

5

오늘 아침에도 동료와 이야기를 나누었습니다. 불행한 일이지만 안전을 위해 기본값을 처리하는 것이 두 가지 이유로 필요하다고 생각합니다.

먼저 동료가 언급했듯이 열거 형에 추가 된 새로운 값에 대해 코드를 미래에 대비합니다. 이것은 가능성처럼 보일 수도 있고 그렇지 않을 수도 있지만 항상 있습니다.

더 중요한 것은 언어 / 컴파일러에 따라 전환 변수에 열거 형의 멤버가 아닌 값을 가질 수 있습니다. 예를 들어 C #에서

MyEnum myEnum = (MyEnum) 3; // This could come from anywhere, maybe parsed from text?
// ... code goes on for a while

switch ( myEnum )
{
    case MyEnum.A:
        // ... handle A case
        break;
    case MyEnum.B:
        // ... handle B case
        break;
}

// ... code that expects either A or B to have happened

단순함을 추가하고 case default:예외를 던져서 "아무것도"발생하지 않지만 "무언가"가 발생해야하는 이상한 경우로부터 자신을 보호했습니다.

불행히도, 기본적으로 더 이상 switch 문을 작성할 때마다 열거 형의 사례를 확인하기 때문입니다. 나는 "기본적으로 던지기"행동이 언어 자체에 의해 (적어도 키워드를 추가함으로써) 시행되기를 정말로 바란다.


3

도달하지 않을 경우에도 기본 사례를 추가하는 것이 좋습니다. 코드가 프로그램에서 나중에 발생하지 않고 "이것이 발생해서는 안됩니다"예외를 즉시 처리하여 신비한 예외를 막거나 오류없이 예기치 않은 결과를 반환하면 디버깅이 훨씬 쉬워집니다.


2

내가 말하다:

에 다른 유형을 추가해보십시오 MyEnum. 그런 다음이 줄을 변경하십시오.

MyEnum myEnum = GetMyEnum();

MyEnum myEnum = SomethingElse;

그런 다음 기본 대 / 소문자 없이 코드를 실행하십시오 . 어떤 행동을 선호합니까?

기본 사례를 사용하면 NULL값 을 트래핑 하고 방지하는 데 유용 할 수 있습니다 NullPointerExceptions.


-1

기본 사례를 주장하여 mach 시간을 절약 할 수있는 방법을 알고 있다면 질문 할 필요가 없습니다. 오류 조건에서 자동으로 아무 작업도 수행 할 수 없습니다. 절대 발생하지 않아야하는 예외를 자동으로 잡습니까? 당신을 따르는 프로그래머에게 "광산"을 남겨 두는 것도 마찬가지로 용납 할 수 없습니다.

코드가 변경되거나 수정되지 않고 100 % 버그가없는 경우 기본 사례를 생략해도됩니다.

Ada (강력한 프로그래밍 언어의 할아버지)는 모든 열거 형이 포함되거나 기본 처리기가없는 한 열거 형에서 스위치를 컴파일하지 않습니다.이 기능은 모든 언어의 위시리스트에 있습니다. Ada 코딩 표준에 따르면 열거 형을 켜면 모든 값을 명시 적으로 처리하고 기본값을 사용하지 않는 것이이 상황을 처리하는 데 선호되는 방법입니다.


왜 모든 -1입니까?
mattnz

2
나는 당신을 -1하지 않았지만, 그것은 당신의 태도 때문일 것이라고 생각합니다.)
Friek
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.