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.