switch 문이나 long if… else chain을 사용해야합니까?


36

종종 switch 문에 대해 들었을 때 긴 if ... else 체인을 대체하는 방법으로 사용되었습니다. 그러나 switch 문을 사용하면 더 많은 코드를 작성하여 if ... else로 작성하는 것 같습니다. 또한 모든 호출에 대한 모든 변수를 동일한 범위로 유지하는 것과 같은 다른 문제가 있습니다 .

다음은 일반적으로 쓰는 흐름을 나타내는 코드입니다 ( diam 덕분에 )

String comment;   // The generated insult.
int which = (int)(Math.random() * 3);  //  Result is 0, 1, or 2.

if (which == 0) {
    comment = "You look so much better than usual.";
} else if (which == 1) {
    comment = "Your work is up to its usual standards.";
} else if (which == 2) {
    comment = "You're quite competent for so little experience.";
} else {
    comment = "Oops -- something is wrong with this code.";
}

그런 다음 그들은 이것을 이것을 다음과 같이 바꾸길 원합니다.

String comment;   // The generated insult.
int which = (int)(Math.random() * 3);  //  Result is 0, 1, or 2.

switch (which) {
    case 0:  
             comment = "You look so much better than usual.";
    break;
    case 1:  
             comment = "Your work is up to its usual standards.";
    break;
    case 2:  
             comment = "You're quite competent for so little experience.";
    break;
    default: 
             comment = "Oops -- something is wrong with this code.";
}

훨씬 더 어색한 구문에서 훨씬 더 많은 코드처럼 보입니다. 그러나 switch 문을 사용하면 실제로 이점이 있습니까?


어. 예, 그것은 확실히 더 커지지 만 C 문장에서만 가능합니다. 케이스 문장에 대한 구문이 너무 추하기 때문입니다.
— 메이슨 휠러


1
가능할 때마다 둘 다 피해야합니다. 조회 대상이 함수 또는 클래스 인 경우에도 데이터 구조를 작성하고 조회를 수행하는 것이 훨씬 좋습니다.
— 케빈 클라인

적어도 .net에서는 스위치가 더 빠릅니다. 나는 Java에 대해 모른다.
— Knerd

사례와 방법의 사전과 하나의 "if"로 리팩토링 가능
— Pavel Yermalovich

답변:


57

이 특정 상황의 경우, 모두 나에게 보인다 if그리고 case가난한 선택입니다. 간단한 배열을 사용합니다.

String comments[] = {
    "You look so much better than usual.",
    "Your work is up to its usual standards.",
    "You're quite competent for so little experience."
};

String comment = comments[(int)(Math.random() * 3)];

참고로 일반적으로를 하드 코딩하는 대신 배열의 크기에 따라 승수를 계산해야합니다 3.

당신이 경우에 관해서는 것 의 폭포에서 케이스 / 스위치의 차이를 사용 if제표 (또는 적어도 하나의 큰 차이는) 그이있다 switch반 자동으로 최적화의 폭포 반면, 수와 값의 밀도에 따라 수 있습니다 if문 잎 컴파일러 선택의 여지가 거의 없지만 코드를 작성하면서 코드를 생성하여 일치하는 것을 찾을 때까지 값을 하나씩 테스트합니다. 세 가지 실제 사례 만 있으면 거의 문제가되지 않지만 숫자가 충분하면 중요 할 수 있습니다.


이 예는 BTW의 예일뿐입니다. 컴파일러가 그렇게 최적화 할 수 있다는 것을
— 몰랐습니다

6
@JBRWilkinson. 이 경우 범위를 벗어난 값은 컴파일러 버그를 통해서만 가능하며 많은 시간을 소비하지 않습니다 (결과를 테스트하는 코드의 버그는 생성 코드와 거의 같습니다). 범위를 벗어난 값이 실제 관심사 인 상황 (예 : 다른 코드에서 색인을 수신 한 경우)에서는 경계를 먼저 확인하고 확인 후에 만 ​​색인으로 사용합니다.
— Jerry Coffin

4
나는이 답변이 그 예에 대해 매우 구체적이라고 생각하지만 그 질문은 그보다 더 일반적인 것입니다 ...
— Khelben

3
@ 켈벤 : 당신이 전체 답변을 읽는 것을 귀찮게하지 않은 것처럼 들립니다. 마지막 단락은 더 넓은 문제를 다룹니다. 그래도 문제가 있습니다 . 진술이나 일련의 진술이 적합한 것으로 생각되는 상황은 거의 없습니다 . 대부분의 경우, 그들은 일종의지도 / 배열 유형을 대체하는 (의료) 대체물이며, 후자를 직접 사용하는 것이 좋습니다. caseif
— Jerry Coffin

1
@Titou : 컴파일러가 완전히 브레인 데드가 아닌 한, 배열은 컴파일 타임에 한 번 빌드되고 그 후에 정적 구조를 사용합니다. 예를 들어 C 또는 C ++ 에서이 작업을 수행 static const하는 경우 항상 존재하는지 확인하기 위해 배열 을 만들고 싶습니다 (그러나 질문에 언어가 제공되지 않았으므로 대답에서 하나를 가정하지 않았습니다) ).
— Jerry Coffin

23

if...else if...체인 의 문제점 은 내가 읽을 때 if프로그램이 무엇을하는지 이해하기 위해 모든 단일 조건을 살펴 봐야 한다는 것입니다. 예를 들어 다음과 같은 것이있을 수 있습니다.

if (a == 1) {
    // stuff
} else if (a == 2) {
    // stuff
} else if (a == 3) {
    // stuff
} else if (b == 1) {
    // stuff
} else if (b == 2) {
    // stuff
}

(분명히 이와 같은 소수의 진술에 대해서는 그렇게 나쁘지 않습니다)

모든 단일 문을 읽지 않고 조건 변수를 반쯤 변경했다는 것을 알 방법이 없습니다. 그러나 switch단일 조건 변수 로 제한 하기 때문에 무슨 일이 일어나고 있는지 한 눈에 알 수 있습니다.

하루의 끝에서, 그러나, 나는 어느 쪽도 선호하지 것 switch또는 체인 if...else if. 종종 더 나은 해결책은 원래 질문이나 다형성 (언어가 지원하는 경우)과 같은 경우에 대한 일종의 점프 테이블 또는 사전입니다. 물론 항상 가능하지는 않지만 switch첫 번째 단계로 피할 수있는 솔루션을 찾고 싶습니다 ...


4
다형성은 코드를 조각화한다는 단점이 있으므로 단일 위치에 비해 이해하기가 어렵습니다. 따라서 변경하기 전에 주저 할 수 있습니다.

왜 점프 테이블 / 사전이 스위치보다 낫습니까?
— Titou

14
switch (which) {
  case 0: comment = "String 1"; break;
  case 1: comment = "String 2"; break;
  case 2: comment = "String 3"; break;
  default: comment = "Oops"; break;
}

이 유형의 스위치 케이스를 작성하는 위의 방법은 상당히 일반적입니다. 부피가 큰 경우 스위치 케이스를 느낀 이유는 신체가 단 한 줄이고 스위치 케이스를 사용하면 브레이크 명령문도 필요했기 때문입니다. 따라서 스위치 케이스의 경우 본체 크기의 두 배입니다. 보다 실질적인 코드를 사용하면 break 문이 본문에 많이 추가되지 않습니다. 한 줄 본문의 경우 case 문과 같은 줄에 코드를 작성하는 것이 일반적입니다.

다른 사람들이 이미 언급했듯이 전환 사례는 의도를보다 명확하게하므로 단일 변수 / 표현식의 값을 기반으로 결정하려고합니다. 내 의견은 순전히 가독성 관점에서 비롯된 것이며 성능에 기반하지 않습니다.


1
스위치를 메소드에 넣고 각각의 경우 return적절한 문자열을 가지면 break명령문을 제거 할 수 있습니다 .
— Robert Harvey

귀하의 솔루션도 가장 빠릅니다.
— Titou

8

이 경우 switch 문은 코드의 의도와보다 명확하게 일치합니다. 단일 값을 기반으로 수행 할 조치를 선택하십시오.

반면 if 문은 읽기가 훨씬 어렵습니다. 진행 상황을 확인하려면 모든 내용을 살펴 봐야합니다. 나에게 그것은 (문자 수는 경우에도 적은 코드의 수 이하로 거기로 정신 분석 약간 높을 수는).


8

나는이 특정 경우에 문자열 배열이 더 좋지만 일반적으로 elseifs 체인보다 switch / case 문을 사용하는 것이 더 좋다는 Jerry에 동의합니다. 읽기가 더 쉽고 때로는 컴파일러가 더 나은 방식으로 최적화 작업을 수행 할 수 있지만 또 다른 이점도 있습니다. 디버그하기가 훨씬 쉽습니다.

해당 스위치를 눌렀을 때 한 번에 여러 if 문을 신중하게 단계별로 실행하는 대신 한 번에 한 단계 만 수행하면됩니다. 키를 너무 빨리 눌렀을 때 키를 빠르게 누르고 넘어 가서 무언가를 잃어 버릴 수 있습니다. 다시 시작합니다.


3

그런 종류의 경우 스위치를 선호합니다. 코드 포인트와 훨씬 잘 일치하고 각 입력 값마다 다른 명령문을 실행합니다. 그 if..else행위는 같은 효과를 달성하기 위해 "속임수"처럼 작용합니다.

switch 성명서도 깨끗합니다. 오타를 쉽게 숨길 수 있습니다. ==

또한 C의 큰 블록의 경우 스위치가 더 빠릅니다.

else..if범위와 같은 (1과 100 사이, 이것을 수행하고, 100과 200 사이를) 그렇게 할 때 또는 C와 같이 문자열과 같은 요소로 전환하려고 할 때 (다른 언어에서 가능) 더 적합 할 수 있습니다. 어느 것도 동일합니다.

C로 프로그래밍 할 때 많은 스위치를 사용하는 경향이 있습니다.


2

효율적이고 간결한 것을 선택한 다음 수행 한 작업뿐만 아니라 그 이유 를 문서화하십시오 .

코드는 원래 작성자가 항상 다시 볼 수있는 것은 아닙니다.

존재하지 않는 코드에 대해 미리 생각 하기 때문에 의도적으로 다른 구현을 선택 하는 경우가 있습니다.


2

나는 일반적으로 두 가지 접근법을 좋아하지 않습니다. 긴 스위치 또는 if 문은 객체 지향 추상화로 리팩토링되기를 구했습니다 (그러나 귀하의 예는 짧지 않고 짧게 분류 할 것입니다).

개인적으로 그런 종류의 코드를 별도의 도우미 메서드로 래핑합니다.

private string GetInsult()
{
    int which = (int)(Math.random() * 3);  //  Result is 0, 1, or 2.

    switch (which) {
        case 0: return "You look so much better than usual.";
        case 1: return "Your work is up to its usual standards.";
        case 2: return "You're quite competent for so little experience.";
        default: return "Oops -- something is wrong with this code.";
    }
}

public void Foo()
{
    string comment = GetInsult();
    Print(comment);
}

스위치를 별도의 메서드에 배치하면 스위치 문 안에 (최소 c #에서는) return 문을 직접 배치 할 수 있으므로 break 문이 필요하지 않으므로 코드를 훨씬 쉽게 읽을 수 있습니다.

그리고 이것은 if / else if / else if 접근법보다 훨씬 좋습니다.


3
나는 개인적으로 문제를 해결하는 "못생긴 것처럼 보이기 때문에 다른 방법으로 넣는"것을 싫어합니다. 어수선한 방법 목록 및 더 나쁜 IMHO 보인다. A) 코드가 어딘가에 복제되었거나 B) 다른 곳에서 유용 할 수있는 경우에만이 작업을 수행합니다
— TheLQ

1
어떤 방법 목록? 그리고 왜 메소드 목록이 코드가 복잡 해지는 것보다 어수선합니까? "우리가 한 번에 모든 것을 볼 수 있도록 모든 것을 하나의 단일 방법으로 유지"나이를지나
— sara

@TheLQ 나는 당신에게 일반적으로 동의하지만,이 경우 "comment ="는 실제로 Pete의 제안에 의해 결정됩니다.
— Titou

0

파이썬에서는 if / elif / else가 좋기 때문에 switch 문이 없습니다.

a = 5

if a==1:
    print "do this"
elif a == 2:
    print "do that"
elif a == 3:
    print "do the other"
elif 3 < a < 9:
    print "do more"
elif 9 <= a < 15:
    print "do nothing"
else:
    print "say sorry"

간단 하죠?


Elif몇 글자가 빠진 if 문입니다. ifswitch 문보다 확실히 문과 같습니다. 파이썬에 스위치가 없다는 사실은 (나처럼) 미워하는 사람이 혼자가 아니라고 생각하게 만듭니다.
— Dan Rosenstark

파이썬 포맷은 stackoverflow에서 작동하지만 programmers.stackexchange.com에서는 작동하지 않습니다 :(
— Christopher Mahan

meta알려진 주제가 아닌 경우 경고를 표시해야합니다 . 증인을 주셔서 감사합니다.
— Dan Rosenstark


1
@Yar, 위키 백과 관리 일을 상기시켜줍니다. (아직 완전히
— 논외

0

C / C # 스타일을 switch특히 성가 시게 하는 것 중 하나는 case값이 리터럴 이라는 주장입니다 . VB / VB.NET의 한 가지 좋은 점은 select/case각 경우를 부울 식으로 만들 수 있다는 것입니다. 즉 편리합니다. 일련의 상호 배타적 인 부울 표현식이 도움이되는 한, if / else ifs가 더 유연하고 타이핑하고 읽는 것이 더 효율적이라는 것은 말할 것도 없습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.