2009-11-25 5 views
1

이 스타일의 switch 문을 if else 문으로 변경해야하는 곳이 궁금합니다.이 switch 문에 코드 냄새가 있습니까?

switch (foo) // foo is an enumerated type 
{ 
    case barOne: 
     if (blahOne) 
     { 
      DoFunction(//parameters specific to barOne); 
      break; 
     } 
    case barTwo: 
     if (blahTwo) 
     { 
      DoFunction(//parameters specific to barTwo); 
      break; 
     } 
    //etc. 
    default: 
     // Whatever happens if none of the case's conditionals are met 
} 

경우 중 하나에 대한 조건이 충족되지 않으면 기본적으로 폴드 스루가 발생합니다. 사례는 매우 유사하며, 점검해야 할 항목과 전달해야하는 항목이 다르기 때문에 switch 문을 사용했습니다. ifelse if를 사용하는

더 나은 것입니까? 그렇지 않으면 체류하기에 충분한 지 알 수 있습니까? 그렇지만 그 타당성에 대한 의견을 말하기에는 불분명합니까? 다형성은 항상 선택 사항이지만 나에게는 과도한 것처럼 보입니다./다른 K & R이 참조하는 경우

+1

이 당신은 내가 일반적으로 그것 때문에 얼마나 추한의 가장 간단한 표현을 제외하고 원을 피하기 –

+0

삼항 쓸 수 있습니다. – Anonymous

+2

두 개의 선택 뒤에 // 등을 적어 두십시오 – yodie

답변

7

어떤 경우에는 이상한 일을하는 것처럼 보입니다. foo == bar1이라면, 그리고 blahOne은 false이지만, blahTwo가 참이라면? 그런 다음 foo가 bar2와 같지 않더라도 foo == bar2의 경우 함수를 호출하여 함수를 호출합니다.

실제로는 예상치 못한 일이지만, 발생한 적이 있다면 디버깅하기가 어려울 수 있습니다. 나는 흐름이 더 간단하기 때문에이 경우에 if else에 투표 할 것입니다. 물론

if (foo == barOne && blahOne) 
{ 
    DoFunction(/*parameters specific to barOne*/); 
} 
else if (foo == barTwo && blahTwo) 
{ 
    DoFunction(/*parameters specific to barTwo*/); 
} 
else 
{ 
    // Handle the fallthrough case. 
} 

, 의도 blahTwo도 foo는 비록 평가 될 수있는 경우! = barTwo는 다음 스위치가 그것을 할 수있는 가장 좋은 방법이 될 수도 있지만, 나는 확실히 몇 가지 설명 주석의 찬성 것 그럴 경우.

+0

이 답변을 통해 코드의 버그를 내 논리에서. 미묘한 버그 (적어도 나를 위해), 그래서 응답을 주셔서 감사합니다. – Anonymous

+0

이것은 확실히가는 길입니다. –

-1

항상 공상 그래서 스위치를 피할 수 있습니다. 보다 진보 된 시험을 가능하게하고 b. 잊어 버리는 것을 피하십시오.

+0

대부분의 사람들이 다른 사람보다 읽기 쉬운 것으로 전환하기 때문에 c)에 동의하지 않으면 안됩니다. b)와 함께, 나는 당신이 그것을 사용하는 방법을 잊었거나 그것의 일부분을 쓰는 것을 잊어 버렸기 때문에 당신이 구조를 사용하는 것을 멈춰야한다고 생각하지 않는다. (foo == 0보다는 0 == foo와 비슷하다.) a)는 여기에 해당되지 않습니다. – Anonymous

+0

출처 : "switch 구문의 의미에 대한 몇 가지 주요 고려 사항이 있습니다. 학교/switch/ifif/ifif chain의 switch 구문을 정의하고 싶습니다." –

1

그것이/다른 사람 또는 스위치 로직, 변수에 저장하는 경우 내에서 매개 변수를 계산하는 것이 더 나을 것 같다 가독성을 개선 한 다음 계산 어떤 매개 변수와 함수 afterwords를 호출합니다.

0

더 많은 옵션이 있습니다, 특히 때 switchif/else if보다 더 읽을 것 같다. 경험적 규칙 : 동일한 데이터에 대해 세 가지 이상의 비교를 수행해야하는 경우 스위치를 사용하십시오.

1

나는 세트를 선호하는 경우/다른-IF 문하지만 무거운 발전과 성장, 스위치 모두 후/경우 다른-경우 부패하기 시작합니다. foo 열거 형에 정의 된 유형 수가 커지면 어떻게 될지 상상해보십시오. 스위치와 if/else-if 전략 모두 꽤 어울리지 않습니다.

어떤 시점에서 DoSomething 함수를 추상화하거나 (전략 패턴 생각) 매개 변수를 DoSomething 함수로 추상화해야합니다 (DoSomething의 프로토 타입에 foo 열거 형을 넣거나 매개 변수를 DoSomething에 형제로 사용하도록합니다). 기본 클래스).

0

코드 냄새가 실제로 표시되지 않습니다. 코드 스 니펫은 매우 읽기 쉽습니다. 내용에 따라 blahOneblahTwo 대표와 코드가 무엇을, 당신은 또한 최초의 열거로를 소성하여 가독성을 향상 할 수 있습니다. 따라서 각각 하나의 if 문으로 2 개의 사례 대신 4 개의 사례가 생깁니다.

1

내가 당신이라면 내가 할 것이다 : 나에게 더 읽기 많이 보인다

if (foo == barOne && blahOne) { 
    DoFunction(/* params specific to barOne */); 
} else if (foo == barTwo && blahTwo) { 
    DoFunction(/* params specific to barTwo */); 
} else { 
    DoDefaultStuff(); 
} 

합니다. 간단한 스위치/케이스를 보증 할 논리가 너무 많습니다.당신은 본질적으로 if에 중첩 if 금액 (그 많은 그것을 꽤입니다) 어떤 경우 또한, ... 당신이 사용하는 것이 좋습니다 &&

+0

그건 내 본능 이었지만, 뭔가 편집하고 싶을 때 코드를 읽을 때 올바른 선택을하기가 더 어려워졌습니다. 즉, barOne과 barTwo는 명확하게 눈에 띄지 않습니다. – yodie

1

나는 실제로 꽤 현재 상황 좋아; 스위치는 enum 값을 기준으로 blahOne 등의 평가를 건너 뛰는 단락 회로로 작동합니다. 내가 제안 할 수있는 유일한 방법은 각 사례 끝에 낙오를 지적하는 주석을 넣는 것인데, 이는 종종 눈에 띄지 않게 놓치기 때문입니다. 그리고 아마도 이것이 왜 이런 식으로 말하는가에 대한 것입니다.

물론 이것은 실제로 의도 된 동작이라고 가정합니다. 그렇지 않다면, 다른 사람들이 말했듯이, 그것은 명백히 틀릴 수도 있습니다.

+0

&& s를 고려해 보면 어쨌든 blahs 평가를 건너 뛰지 않겠습니까? – yodie

+0

나는 단지 (블아 넘)의 최적화로서 그것에 대해 생각하고 있었다 ... 다른 경우 (블라우) ... 이전의 것들은 특정 상태에서 건너 뛸 수있는 것들; 많은 수의 분기가있는 긴밀한 루프에서는 깔끔한 최적화가 될 수 있습니다. 그러나 나는 받아 들인 대답에 OP의 의견이 이것이 어쨌든 원하는 행동이 아니었다는 것을 나타냅니다. – Kieron

1

와우, "코드 냄새"또는 버그일까요? 나는 그 코드를보고 즉시 "옳지 않다"고 생각합니다.

스위치 케이스 통과는 코드 주석에 분명하게 문서화되어야하며, 애매한 경우에는 양쪽 정렬을해야합니다.

자바가 나왔을 때 나는 실망했고 15 년 전 C의 switch 선언문의 기본 오류 수정 동작을 수정하지 못했다. 경우 또는 기본 절에서

는 마지막 문장 만 "위해 fallthrough"문 (Fallthrough statement을 §)에있을 수 있습니다 : 만약 당신이 원하는 경우, 이 필요 명시 적 fallthrough 문, 그것을 해결 한 이동 이 절의 끝에서 다음 절의 첫 번째 명령문으로 제어가 흐르도록 지시하십시오. 그렇지 않으면 "switch"문 끝으로 제어가 넘어갑니다.

2

제어 흐름이 의견과 상충 될 수 있으므로 게시 된 코드가 확실히 악취가납니다.

foo가 barOne이고 blahOne이 false이고 blahTwo가 true 인 경우 barTwo와 관련된 매개 변수로 DoFunction()이 호출됩니다. 하지만 foo는 bar입니다. baroo는 아닙니다.

어쩌면 당신이 정말로 의도 한 바는 다음과 같았습니다. 내 생각에는 가을 스루 및 냄새가 없었습니다.

switch (foo) // foo is an enumerated type 
{ 
    case barOne: 
     if (blahOne) 
      DoFunction(//parameters specific to barOne); 
     break; 
    case barTwo: 
     if (blahTwo) 
      DoFunction(//parameters specific to barTwo); 
     break; 
    //etc. 
    default: 
     // Whatever happens if none of the case's conditionals are met 
} 
+0

그게 내가 원하는게 아니야. 휴식은 절 안에 있어야합니다. 위의 설명에서 추론을 설명했습니다. – Anonymous

+0

수수께끼. 당신의 받아 들여진 응답은 나의 대답과 똑같은 일을합니다. 당신이 수락 한 대답에 기술 된 버그는 정확히 내 대답에서 기술 한 버그입니다. 버그는 절이 절 안에 있으며, 의도가 있어도 도움이되지 않을 것입니다. /else 또는 스위치가 문체를 선호하는 경우. 다른 사람들이 말했듯이, 3 개 이상의 절이 있으면 전환을 권장합니다. –

+0

그들은 같은 일을하지 않습니다. 스위치를 사용하면 switch 절이 case가 충족되면 (따라서 기본값에 도달하지 못함) case의 조건부가 true인지 false인지에 관계없이 중단됩니다. 이것은 분명히 OP가 그/그녀가 사용한 방법을 사용한 이유입니다. else if를 사용하고 괄호 (barOne && blahOne)에서 두 조건을 모두 테스트하면 barOne이 true이지만 blahOne이 false 인 경우 'else'에 도달 할 수 있습니다. 당신의 switch 절은 그렇지 않습니다. 부수적으로, 누군가가 당신의 대답을 선택했는지 아닌지에 대해 화를 내지 마십시오. – trikker

0

이 switch 문을 확장하려는 것으로 보이므로 코드도 악취가납니다. 내 이해를 위해 긴 스위치 또는 if/else 블록을 실행하는 것은 비효율적이며 읽기가 어렵습니다.

솔직히 작은 것들에 대해서는 std :: map을 사용하고 더 큰 것들에 대해서는 unordered map을 사용하는 것이 좋습니다.

또는 (이 OO을 따르기 때문에 IMO, 더 나은,) 당신은 클래스를 사용할 수

void DoFunction(someType param){ 
    //do what you like 
} 

class Case{ 
    public: 
     Case(someType param_, bool myBlah_): param(param_), myBlah(myBlah_) {} 

    void eval() { 
     if (myBlah) 
      DoFunction(param); 
    } 
private: 
    someType param; 
    bool myBlah; 
}; 

void DoSomething(Case foo){ 
    foo.eval(); 
} 
관련 문제