Switch 문 폴 스루… 허용되어야합니까? [닫은]


120

내가 기억할 수있는 한 나는 switch 문 폴 스루 사용을 피했다. 사실, 나는 그것이 스위치 문장의 버그에 지나지 않는다는 것을 일찍 내 머리에 뚫었 기 때문에 가능한 일을 할 수있는 방법으로 내 의식에 들어가는 것을 기억할 수 없습니다. 그러나 오늘 나는 그것을 디자인에 의해 사용하는 일부 코드를 만났고, 이것은 커뮤니티의 모든 사람들이 switch 문 폴 스루에 대해 어떻게 생각하는지 즉시 궁금해했습니다.

프로그래밍 언어가 명시 적으로 허용해서는 안되는 것입니까 (해결책을 제공하지만 C #처럼) 아니면 프로그래머의 손에 맡길 수있을만큼 강력한 언어의 기능입니까?

편집 : 나는 폴스 루가 의미하는 바에 대해 충분히 구체적이지 않았습니다. 이 유형을 많이 사용합니다.

    switch(m_loadAnimSubCt){
        case 0:
        case 1:
            // Do something
            break;
        case 2:
        case 3:
        case 4:
            // Do something
            break;
   }

그러나 나는 이와 같은 것에 대해 걱정합니다.

   switch(m_loadAnimSubCt){
        case 0:
        case 1:
            // Do something, but fall through to the other cases
            // after doing it.

        case 2:
        case 3:
        case 4:
            // Do something else.
            break;
   }

이렇게하면 case가 0, 1 일 때마다 switch 문에서 모든 작업을 수행합니다. 나는 이것을 의도적으로 보았고 switch 문을 이런 방식으로 사용해야한다는 데 동의하는지 모르겠습니다. 첫 번째 코드 예제는 매우 유용하고 안전하다고 생각합니다. 두 번째는 위험 해 보입니다.


dupe

51
건설적이지 않다는 것에 동의하지 않습니다. 질문에 대한 27 명의 찬성표는 이런 식으로 느끼는 다른 사람들도 있다고 말합니다.
Wes Modes

2
"건설적이지 않다"는 것은 오래되고 다소 모호한 가까운 이유입니다. 오늘날 이러한 질문은 순전히 의견을 기반으로 한 것으로 종결되도록 플래그를 지정할 수 있으며 그래야합니다. SO는 '피처 X에 대한 내 의견에 대한 "커뮤니티"의 의견이 아니라 코드 또는 디자인에 대한 답변 가능한 질문입니다. Programmers.SE가 더 적합 할 것이지만 그럼에도 불구하고 그러한 광범위하고 의견 중심 질문의 가치는 여전히 매우 모호합니다.
underscore_d

1
fallthrough가 사용되는 매우 명확한 사용 사례가 있으므로 왜 그것이 의견 기반인지 확실하지 않습니다. 이 질문이 약간 불분명하다는 데 동의하지만 건설적이지 않은 것으로 닫혀서는 안됩니다. 아마도 "폴 스루는 언제 사용됩니까?"라는 더 명확한 사례로 편집 할 수 있습니다. 명확한 답이 있습니다. 좋은 C ++ 텍스트는이 문제를 다루며, 새로운 코더 (또는 다른 언어의 경험이 더 많은 코더)에게는 혼란 스럽기 때문에 SO에게 좋은 질문으로 보입니다. 사실, 그것은 프로토 타입 적으로 좋은 SO 질문 처럼 보입니다 . 요청 된 방식이 완벽하지 않더라도.
eric

답변:


89

그것은 당신이 폴 스루라고 생각하는 것에 달려 있습니다. 나는 이런 종류의 일로 괜찮습니다.

switch (value)
{
  case 0:
    result = ZERO_DIGIT;
    break;

  case 1:
  case 3:
  case 5:
  case 7:
  case 9:
     result = ODD_DIGIT;
     break;

  case 2:
  case 4:
  case 6:
  case 8:
     result = EVEN_DIGIT;
     break;
}

그러나 케이스 라벨 뒤에 다른 케이스 라벨로 넘어가는 코드가 있다면, 저는 거의 항상 그 악한 것으로 간주합니다. 아마도 공통 코드를 함수로 옮기고 두 곳에서 호출하는 것이 더 좋은 생각 일 것입니다.

그리고 "악"C ++ FAQ 정의를 사용합니다.


나는 당신의 의견에 동의합니다 : 나는 당신의 예제를 폴 스루라고 생각하지 않으며 폴 스루를 통해 여러 코드 블록을 실행하려는 경우가 있다면 더 나은 방법이있을 것입니다.
Dave DuPlantis

10
단순히 "악"의 정의에 +1. 감사합니다 ;-)
Joachim Sauer

나는 당신의 요점을 이해하고 당신이 옳지 만 당신의 모범은 정말 나쁩니다. 아무도 이와 같은 테스트 숫자를 테스트해서는 안됩니다. Scnr, 당신의 대답은 어쨌든 맞습니다.
Tim Büthe 2010 년

예를 들어, 그것은 C #이 허용하지 않는 바로 그 것입니다. 이유가있을 것 같습니다 :-)
Joey

슬프게도 악의 정의는 사라 오프라인을 갖고있는 것 같아요
HopefullyHelpful

57

양날의 검입니다. 때로는 매우 유용하지만 종종 위험합니다.

언제 좋은가요? 10 개의 케이스를 모두 동일한 방식으로 처리하려면 ...

switch (c) {
  case 1:
  case 2:
            ... Do some of the work ...
            /* FALLTHROUGH */
  case 17:
            ... Do something ...
            break;
  case 5:
  case 43:
            ... Do something else ...
            break;
}

내가 좋아하는 한 가지 규칙은 휴식을 제외하고 멋진 일을 한 적이 있다면 / * FALLTHROUGH * /라는 명확한 주석이 필요하다는 것입니다.


3
+1! 나는 그것이 때때로 옳은 대답이라는 것에 동의하고, 설계 상 주석을 달아야한다는 데 두 배로 동의합니다. (코드 검토에서 다른 개발자 코멘트를 비어 있지 않은 설계에 의해 작성합니다. 그런 일은 발생하지 않습니다. 지원되지 않는 C # 상점입니다. :)
John Rudy

4
나는 적절한 경우 내 코드에서 / * FALL THROUGH * / 주석을 사용합니다. =]
strager

2
PC-Lint의 경우 / *-fallthrough * /를 삽입해야합니다. 그렇지 않으면 불평합니다.
Steve Melnikoff

1
그래도 의도적 인 행동임을 분명히하고 if(condition > 1 && condition <10) {condition = 1}; switch(...싶다면 케이스를 (명확하게 보이기 위해) 저장하는 것이 좋을 수 있으며 , 모든 사람들이 해당 케이스가 동일한 액션을 트리거하기를 원한다는 것을 알 수 있습니다.
Mark

1
이것은 여전히 ​​끔찍한 코딩입니다. 첫 번째 경우는 함수를 호출하고 두 번째 경우는 동일한 함수를 호출 한 다음 두 번째 함수를 호출해야합니다.
BlueRaja-Danny Pflughoeft

21

Duff의 장치에 대해 들어 보셨습니까 ? 이것은 스위치 폴 스루를 사용하는 좋은 예입니다.

거의 모든 언어 기능처럼 사용할 수 있고 남용 될 수있는 기능입니다.


매일 새로운 것을 배우십시오-감사합니다! 그래도 그런 뒤틀림을 겪는 불쌍한 개발자를 생각합니다.
Justin R.

와우, 그것은 당신의 두뇌를 감싸는 꽤 무언가입니다.
Fostah

6
그 기사에서 더프가 인용 한 주석에 주목하라. "이 코드는 그 논쟁에서 일종의 논쟁을 형성하지만, 그것이 찬성인지 반대인지는 확실하지 않다."
John Carter

Duff의 장치는 분명히 사악합니다
Marjeta 2013-04-23

21

폴 스루는 당신이하는 일에 따라 정말 편리한 일입니다. 옵션을 정렬하는 깔끔하고 이해하기 쉬운 방법을 고려하십시오.

switch ($someoption) {
  case 'a':
  case 'b':
  case 'c':
    // Do something
    break;

  case 'd':
  case 'e':
    // Do something else
    break;
}

if / else로 이것을한다고 상상해보십시오. 엉망이 될 것입니다.


1
이 유형의 폴스 루가 매우 유용하다고 생각합니다.
Mitchel Sellers

'무언가'가 스위치보다 조금 이상하다면 if / else보다 엉망이 될 것입니다. if / else를 사용하면 테스트되는 변수가 어디에서나 명확합니다. 심지어이 작은 예에 경우 / 다른 내 눈에 그렇게 나쁘지 보이지 않아
grenix

10

몇 번은 매우 유용 할 수 있지만 일반적으로 폴 스루는 원하는 동작이 아닙니다. 폴 스루는 허용되어야하지만 암시 적이 어서는 안됩니다.

예를 들어 일부 데이터의 이전 버전을 업데이트하려면 다음을 수행하십시오.

switch (version) {
    case 1:
        // Update some stuff
    case 2:
        // Update more stuff
    case 3:
        // Update even more stuff
    case 4:
        // And so on
}

6

스위치의 폴백에 대해 다른 구문을 원합니다.

switch(myParam)
{
  case 0 or 1 or 2:
    // Do something;
    break;
  case 3 or 4:
    // Do something else;
    break;
}

참고 : 플래그를 사용하여 열거 형의 모든 케이스를 선언하면 열거 형으로 이미 가능할 것입니다. 그렇게 나쁘게 들리지는 않습니다. 케이스는 이미 열거 형의 일부가 될 수 있습니다.

아마도 이것은 확장 메서드를 사용하는 유창한 인터페이스에 대한 좋은 사례 (말장난이 아님)일까요? 뭐, 음 ...

int value = 10;
value.Switch()
  .Case(() => { /* Do something; */ }, new {0, 1, 2})
  .Case(() => { /* Do something else */ } new {3, 4})
  .Default(() => { /* Do the default case; */ });

가독성이 떨어질 수 있지만 : P


1
나는 첫 번째 제안을 많이 좋아합니다. 그것은 매우 잘 읽고 몇 줄의 코드를 절약합니다. 두 번째는 내 두뇌를 감싸는 데 1 분이 걸렸지 만 말이되지만 엉망이 될 준비가 된 것 같습니다.
Fostah

1
네, 그게 제가 생각했던 것입니다. 기존 언어 구조를 사용하여 전환하는 다른 방법을 찾기 위해 제가 내려 놓은 무작위 방귀였습니다.
Erik van Brakel

이 질문을 통해 실제로 이것을 좋아합니다! 이것의 가독성을 향상시키는 방법에 대한 아이디어가 있었지만 여러 줄로 된 주석을 게시 할 수 없습니다. (누군가 이것을 POC처럼 구현해야하고 구현하고 사용하는 것이 재미있어 보입니다 (:
Victor Elias

5

다른 것과 마찬가지로 조심스럽게 사용하면 우아한 도구가 될 수 있습니다.

그러나 단점 은 사용 하지 않는 것을 정당화 하고 마침내 더 이상 허용하지 않는 것 이상이라고 생각합니다 (C #). 문제는 다음과 같습니다.

  • 휴식을 "잊기"쉽습니다.
  • 생략 된 중단이 의도적 이라는 것이 코드 관리자 에게 항상 분명한 것은 아닙니다.

스위치 / 케이스 폴 스루 사용 :

switch (x)
{
case 1:
case 2:
case 3:
 Do something
 break;
}

스위치 / 케이스 폴 스루 사용 :

switch (x)
{
case 1:
    Some code
case 2:
    Some more code
case 3:
    Even more code
    break;
}

이것은 내 의견으로는 전혀 손실없이 if / else 구문을 사용하여 다시 작성할 수 있습니다.

내 마지막 단어 : 이 스타일이 사용되고 잘 이해되는 레거시 코드를 유지하지 않는 한 , 나쁜 예 에서와 같이 폴 스루 케이스 레이블을 멀리하십시오 .


3
if () 및 goto ...를 사용하여 대부분의 언어 구문을 다시 작성할 수 있지만 명시 적 구문을 포기하는 것은 정당하지 않습니다.
Shog9

2
알고 있지만 "케이스 1 : 일부 코드 케이스 2 : 더 많은 코드 케이스 3 : 최종 코드 브레이크"를 명시 적으로 사용하는 스위치 / 케이스 구조를 알고 있습니다. if / else if (내 의견)를 사용하여 다시 작성할 수 있으며 다시 작성해야합니다.
steffenj

1
스위치는 if-elses 목록보다 몇 배 더 빠를 수 있습니다. Switch는 점프 테이블을 사용하거나 불가능한 경우 조건부 점프의 선형 목록 대신 의사 결정 트리에서 조건부 점프를 구성합니다. 잘 구조화 된 중첩 If-else 문은 기껏해야 똑같이 빠릅니다.
Jochem Kuijpers

4

강력하고 위험합니다. 폴 스루의 가장 큰 문제는 그것이 명시 적이 지 않다는 것입니다. 예를 들어, 폴스 루가있는 스위치가있는 자주 편집되는 코드를 발견하면 이것이 의도적 인 것이며 버그가 아니라는 것을 어떻게 알 수 있습니까?

내가 사용하는 곳 어디에서나 적절하게 주석을 달았는지 확인합니다.

switch($var) {
    case 'first':
        // Fall-through
    case 'second':
        i++;
        break;
 }

2
'first'사례에 대한 코드가 없으면 의도가 분명합니다. 거기에 코드를 작성하고 'second'케이스에 대한 코드도 실행하려면 주석이 중요합니다. 그러나 어쨌든 나는 그 시나리오를 피할 것입니다.
Joel Coehoorn

1
@Joel-나는 완전히 동의합니다. 내 가게에서는 이런 경우 댓글을 달았지만 가독성이 떨어 졌다고 생각한다. 그래도 코드가 있으면 fallthrough 주석을 입력하십시오.
Fred Larson

"명확하지 않음"이란 무엇을 의미합니까? 이것이 우리가 깨는 이유입니다. 다른 언어로도 가능합니다. 순서대로 언어를 배우지 못한 사람들에게만 문제가됩니다. C #은 imho에 대한 이유없이 기본 케이스 ffs를 요구합니다.
mckenzm

3

첫 번째 예제에서와 같이 폴 스루를 사용하는 것은 분명히 괜찮으며 실제 폴 스루라고 생각하지 않습니다.

두 번째 예는 위험하며 (광범위하게 설명하지 않으면) 명확하지 않습니다. 저는 학생들에게 주석 블록을 할당하는 노력의 가치가 있다고 생각 하지 않는 한 이러한 구성을 사용하지 않도록 가르칩니다 . 이는 이것이 의도적 인 실패이며이 솔루션이 대안보다 나은 이유를 설명합니다. 이것은 엉성한 사용을 막지 만 이점으로 사용되는 경우에는 여전히 허용됩니다.

이것은 누군가가 코딩 표준을 위반하기를 원했을 때 우주 프로젝트에서했던 것과 거의 동일합니다. 그들은 섭리를 신청해야했습니다 (그리고 판결에 대한 조언을 요청 받았습니다).


2

나는 내 switch진술이 실패하는 것을 좋아하지 않습니다. 너무 오류가 많고 읽기가 어렵습니다. 유일한 예외는 여러 case명령문이 모두 정확히 동일한 작업을 수행 하는 경우입니다.

switch 문의 여러 분기에서 사용하려는 공통 코드가있는 경우 모든 분기에서 호출 할 수있는 별도의 공통 함수로 추출합니다.


1

어떤 경우에는 폴 스루를 사용하는 것이 프로그래머의 게으름 행위입니다. 일련의 || 예를 들어, 대신 일련의 '범용'스위치 케이스를 사용합니다.

즉, 결국에는 특히 도움이된다는 것을 알게 되었습니다. 어쨌든 옵션이 필요하다는 것을 알지만 (예를 들어 메뉴 응답에서) 아직 모든 선택을 구현하지 않았을 습니다. 마찬가지로 'a'와 'A'모두에 대해 폴 스루를 수행하는 경우 복합 if 문보다 스위치 폴 스루를 사용하는 것이 훨씬 더 깨끗합니다.

아마도 스타일과 프로그래머가 생각하는 방식의 문제 일 수 있지만 일반적으로 '안전'이라는 이름으로 언어의 구성 요소를 제거하는 것을 좋아하지 않습니다. 이것이 제가 C와 그 변형 / 후손을 선호하는 이유입니다. 자바. 나는 "이유"가 없을 때에도 포인터 등으로 주위를 돌아 다니는 것을 좋아한다.


엄밀히 말하자면. switch 문은 설정된 값을 통해 일련의 특정 코드 위치로 이동합니다. 컴파일러는 이러한 것들을 포착 할 가능성이 있지만 일련의 또는 문에 대한 switch 문에 대한 속도 및 정확성 값이 있습니다. p가 0이거나 p가 1이거나 p가 2이면 코드에서 p = 2 위치로 점프하는 대신 실제로 p가 0이고 p가 1인지 평가해야했습니다. p0, p1과 동일합니다. 그러나 나는 그들을 확인할 필요가 없었다.
Tatarize

1

폴 스루는 코드 블록에 대한 점프 테이블로 사용되는 경우에만 사용해야합니다. 더 많은 케이스 이전에 무조건적인 중단이있는 코드 부분이 있으면 모든 케이스 그룹이 그런 방식으로 종료되어야합니다.

다른 것은 "악"입니다.

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