사용하는 장점 / 단점은 무엇입니까 switch
대 문을 if/else
C #에서이. 코드의 모양 이외의 다른 점이 있다고 상상할 수 없습니다.
결과 IL 또는 관련 런타임 성능이 근본적으로 다른 이유가 있습니까?
사용하는 장점 / 단점은 무엇입니까 switch
대 문을 if/else
C #에서이. 코드의 모양 이외의 다른 점이 있다고 상상할 수 없습니다.
결과 IL 또는 관련 런타임 성능이 근본적으로 다른 이유가 있습니까?
답변:
SWITCH 문은 디버그 또는 호환성 모드의 IF와 동일한 어셈블리 만 생성합니다. 릴리스에서는 O (1) 인 MSIL 'switch'문을 통해 점프 테이블로 컴파일됩니다.
C # (다른 많은 언어와 달리)은 문자열 상수를 켤 수 있으며 약간 다르게 작동합니다. 임의 길이의 문자열에 대한 점프 테이블을 작성하는 것은 실용적이지 않으므로 대부분의 경우 이러한 스위치는 IF 스택으로 컴파일됩니다.
그러나 오버 헤드를 처리 할 수있는 조건 수가 충분하면 C # 컴파일러는 HashTable 개체를 만들고 문자열 상수로 채우고 해당 테이블을 조회 한 다음 점프합니다. 해시 테이블 조회는 엄격하게 O (1)가 아니며 눈에 띄는 일정한 비용이 있지만 대소 문자 레이블 수가 많으면 IF의 각 문자열 상수와 비교할 때보 다 훨씬 빠릅니다.
요약하면 조건 수가 5 이상인 경우 IF보다 SWITCH를 선호하고 그렇지 않으면 더 나은 것을 사용하십시오.
일반적으로 (모든 언어와 모든 컴파일러를 고려하면) 스위치 문은 컴파일러가 스위치 문에서 점프 테이블을 생성하기 쉽기 때문에 if / else 문보다 더 효율적일 수 있습니다. 적절한 제약 조건이 주어지면 if / else 문에 대해 동일한 작업을 수행 할 수는 있지만 훨씬 더 어렵습니다.
C #의 경우에도 마찬가지이지만 다른 이유로도 마찬가지입니다.
많은 수의 문자열을 사용하면 컴파일러에서 해시 테이블을 사용하여 점프를 구현하므로 switch 문을 사용하면 성능이 크게 향상됩니다.
적은 수의 문자열을 사용하면 둘 사이의 성능이 동일합니다.
이 경우 C # 컴파일러는 점프 테이블을 생성하지 않기 때문입니다. 대신 IF / ELSE 블록과 같은 MSIL을 생성합니다.
jitted가 점프 테이블을 사용하여 스위치 명령문을 구현하는 "스위치 명령문"MSIL 명령이 있습니다. 그러나 정수 유형에서만 작동합니다 (이 질문은 문자열에 대해 묻습니다).
적은 수의 문자열의 경우 컴파일러가 IF / ELSE 블록을 생성하는 것이 더 효율적이며 해시 테이블을 사용하는 것입니다.
처음에 이것을 알았을 때 IF / ELSE 블록이 적은 수의 문자열과 함께 사용 되었기 때문에 컴파일러는 많은 수의 문자열에 대해 동일한 변환을 수행했다고 가정했습니다.
이것은 잘못되었습니다. 'IMA'는 이것을 나에게 지적하기에 충분히 친절했습니다 (음. 그는 친절하지 않았지만 그는 옳았습니다.
또한 MSIL에 "스위치"명령이 없다는 것에 대한 본론을 세웠습니다 (스위치 기본 요소가있는 경우 해시 테이블과 함께 사용하지 않은 이유를 알았으므로 스위치 기본 요소가 없어야합니다. ...). 이것은 모두 틀렸고, 엄청나게 바보였습니다. 다시 'IMA'가 이것을 지적했습니다.
가장 높은 등급의 게시물이기 때문에 여기에서 업데이트했으며 허용되는 답변입니다.
그러나 REP가 잘못되었다고 생각하지 않기 때문에 Community Wiki로 만들었습니다. 기회가 생기면 투표 'ima'의 게시물을 올리십시오.
선호하는 세 가지 이유 switch
:
네이티브 코드를 대상으로하는 컴파일러는 종종 switch 문을 하나의 조건부 분기와 간접 점프 로 컴파일 할 수 있지만 if
s 시퀀스 에는 일련의 조건부 분기 가 필요합니다 . 사례의 밀도에 따라 사례 진술을 효율적으로 컴파일하는 방법에 대해 많은 학습 논문이 작성되었습니다. 일부는 lcc 컴파일러 페이지 에서 링크됩니다 . (Lcc는 스위치를위한 더 혁신적인 컴파일러 중 하나를 가졌습니다.)
switch 문은 상호 배타적 인 대안 중에서 선택 되며 스위치 구문 은이 제어 흐름을 프로그래머에게보다 투명하게 만들고 if-then-else 문의 중첩을 만듭니다.
ML 및 Haskell을 포함한 일부 언어에서는 컴파일러가 사례를 생략했는지 확인합니다 . 이 기능을 ML 및 Haskell의 주요 장점 중 하나로 생각합니다. C #이 이것을 할 수 있는지 모르겠습니다.
일화 : 평생 공로상을 수상한 강연에서 Tony Hoare가 자신의 경력에서 한 모든 일에 대해 가장 자랑스럽게 생각하는 세 가지가 있다고 들었습니다.
case
명령문을 )나는 없이 사는 상상할 수 없습니다switch
.
컴파일러는 약간의 차이 (Knuth, anyone?)를 사용하여 거의 모든 것을 동일한 코드로 최적화 할 것입니다.
차이점은 switch 문이 다른 문을 함께 묶으면 15 개보다 깨끗하다는 것입니다.
친구는 친구가 if-else 문을 쌓아 두지 못하게합니다.
실제로 switch 문이 더 효율적입니다. 컴파일러는 if / else 문으로는 찾을 수없는 조회 테이블에 최적화합니다. 단점은 switch 문을 변수 값과 함께 사용할 수 없다는 것입니다.
당신은 할 수 없습니다 :
switch(variable)
{
case someVariable
break;
default:
break;
}
그건 그래야만 해
switch(variable)
{
case CONSTANT_VALUE;
break;
default:
break;
}
나는 다른 사람이 스위치 진술의 가정 된 효율성 이점이 거의 똑같이 가능성이있는 다양한 경우에 달려 있다고 (명백한?) 지점을 제기하는 것을 보지 못했습니다. 값 중 하나 (또는 몇 개)가 훨씬 가능성이 높은 경우 가장 일반적인 경우를 먼저 확인하여 if-then-else 래더가 훨씬 빠릅니다.
예를 들어,
if (x==0) then {
// do one thing
} else if (x==1) {
// do the other thing
} else if (x==2) {
// do the third thing
}
vs
switch(x) {
case 0:
// do one thing
break;
case 1:
// do the other thing
break;
case 2:
// do the third thing
break;
}
x가 시간의 90 % 인 경우 "if-else"코드는 스위치 기반 코드보다 두 배 빠릅니다. 컴파일러가 "스위치"를 일종의 영리한 테이블 기반 goto로 바꾸어도 단순히 0을 확인하는 것만 큼 빠르지는 않습니다.
switch
호환 switch
가능 하면 문장이 더 좋습니다 (가독성 이 높고 때로는 더 빠름). 당신이 알고있는 경우 하나의 경우가 훨씬 더 가능성이 있다고, 당신은 형성이를 뽑을 수 if
- else
- switch
구조를하고 더 빨리 잴 수 있다면 , 당신은에있는 것을두고 (반복, 필요한 경우.) IMO이 여전히 합리적으로 읽을 수.. 는 IF switch
퇴화와이 너무 작 도착하는로 변환하는 작업의 대부분을 할 것입니다 정규식 - 대체 else if
쇄를.
부가 주제이지만, 나는 종종 걱정하고 (더 자주 볼 수 있음) if
/ else
및switch
너무 많은 경우에 진술이 너무 커집니다. 이들은 종종 유지 보수성을 손상시킵니다.
일반적인 범인은 다음과 같습니다.
고치다:
이것은 실제로 귀하의 질문에 대답하지는 않지만 컴파일 된 버전 사이에는 거의 차이가 없으므로 의도를 가장 잘 설명하는 방식으로 코드를 작성하는 것이 좋습니다. 컴파일러가 예상 한 작업을 수행 할 가능성이 높을뿐만 아니라 다른 사람이 코드를보다 쉽게 유지 관리 할 수 있습니다.
하나의 변수 / 속성 값을 기반으로 프로그램을 분기하려는 의도가 있다면 switch 문은 그 의도를 가장 잘 나타냅니다.
다른 변수 / 속성 / 조건에 따라 프로그램을 분기하려는 의도라면 if / else if 체인이 그 의도를 가장 잘 나타냅니다.
나는 코디가 break 명령을 잊어 버린 사람들에 대해 옳다는 것을 인정할 것이지만, {}가 잘못되는 블록이 조건문에 있어야하는 행이 잘못되면 사람들이 복잡 해지는 것을 자주 볼 수있다. 한 줄이 있어도 항상 if 문에 {}를 포함 시키는 이유 중 하나입니다 . 읽는 것이 더 쉬울뿐만 아니라 조건부에서 다른 줄을 추가해야하는 경우 추가하는 것을 잊을 수 없습니다.
관심 질문. 이것은 몇 주 전에 직장에서 나타 났으며 예제 스 니펫을 작성하고 .NET Reflector에서 보는 것으로 답을 찾았습니다 (반사판은 굉장합니다 !! 나는 그것을 좋아합니다).
이것이 우리가 발견 한 것입니다. 문자열 이외의 다른 유효한 스위치 문은 스위치 문으로 IL에 컴파일됩니다. 그러나 문자열 인 경우 IL에서 if / else if / else로 다시 작성됩니다. 따라서 우리의 경우 switch 문이 문자열을 비교하는 방법, 예를 들어 대 / 소문자를 구분하는 방법을 알고 싶었고 리플렉터는 신속하게 답변을주었습니다. 이것은 알기에 유용했습니다.
문자열을 대 / 소문자를 구분하여 비교하려면 String을 수행하는 것보다 빠르기 때문에 switch 문을 사용할 수 있습니다 .if / else에서 비교하십시오. (편집 : 실제 성능 테스트의 경우 빠른 속도, 문자열 켜기 또는 다른 유형 켜기?
switch (myString.ToLower())
{
// not a good solution
}
가장 좋은 방법은 다음과 같이 스위치 구문이 의미가있는 경우 사용하는 것입니다.
switch 문에 공급할 값을 조작해야하는 경우 (전환 할 임시 변수 작성) if / else 제어문을 사용해야합니다.
업데이트:
문자열을 대문자 (예 :)로 변환하는 것이 좋습니다. 예를 들어 ToUpper()
Just-In-Time 컴파일러가와 비교할 때 수행 할 수있는 최적화가 추가 되었기 때문 ToLower()
입니다. 그것은 미세 최적화이지만, 긴밀한 루프에서는 유용 할 수 있습니다.
약간의 참고 사항 :
switch 문의 가독성을 높이려면 다음을 시도하십시오.
switch 문은 if if if보다 빠릅니다. BlackWasp에서 제공 한 속도 테스트가 있습니다
http://www.blackwasp.co.uk/SpeedTestIfElseSwitch.aspx
--확인 해봐
그러나 설명하려는 가능성에 크게 의존하지만 가능할 때마다 switch 문을 사용하려고합니다.
C #뿐만 아니라 모든 C 기반 언어는 스위치가 상수로 제한되므로 "점프 테이블"을 사용하여 매우 효율적인 코드를 생성 할 수 있다고 생각합니다. C 사례는 실제로 오래된 FORTRAN 계산 GOTO이지만, C # 사례는 여전히 상수에 대해 테스트됩니다.
옵티마이 저가 동일한 코드를 작성할 수있는 경우는 아닙니다. 예를 들어,
if(a == 3){ //...
} else if (a == 5 || a == 7){ //...
} else {//...
}
그것들은 복합 부울이므로 생성 된 코드는 값을 계산하고 단락시켜야합니다. 이제 동등한 것을 고려하십시오
switch(a){
case 3: // ...
break;
case 5:
case 7: //...
break;
default: //...
}
이것은로 컴파일 할 수 있습니다
BTABL: *
B3: addr of 3 code
B5:
B7: addr of 5,7 code
load 0,1 ino reg X based on value
jump indirect through BTABL+x
컴파일러에게 OR 및 동등성 테스트를 계산할 필요가 없음을 암시 적으로 알리기 때문입니다.
내 CSS 교수는 사람들이 휴식을 잊어 버렸거나 잘못 사용했기 때문에 진술을 전환하지 말 것을 제안했습니다. 나는 그가 말한 것을 정확하게 기억할 수는 없지만 스위치 문장 (몇 년 전)의 예를 보여준 일부 코드 기반을 살펴보면 엄청난 실수가있었습니다.
방금 주목 한 것은 if / else 및 switch 문을 결합 할 수 있다는 것입니다! 전제 조건을 확인해야 할 때 매우 유용합니다.
if (string.IsNullOrEmpty(line))
{
//skip empty lines
}
else switch (line.Substring(0,1))
{
case "1":
Console.WriteLine(line);
break;
case "9":
Console.WriteLine(line);
break;
default:
break;
}
switch 문은 기본적으로 평등에 대한 비교입니다. 키보드 이벤트는 코드를 쉽게 작성하고 읽을 수있을 때 switch statement에 비해 큰 장점이 있으며 if elseif 문이 있으면 {bracket}이 없으면 문제가 발생할 수 있습니다.
char abc;
switch(abc)
{
case a: break;
case b: break;
case c: break;
case d: break;
}
if elseif 문은 하나 이상의 솔루션에 적합합니다. (AmountOfApples가 5보다 크고 & AmountOfApples가 10보다 작 으면 10) 사과를 판매하는 경우 다른 경우 사과를 저장하십시오. 나는 C #이나 C ++을 쓰지 않지만 자바를 배우기 전에 배우고 그들은 가까운 언어입니다.
switch 문의 단점 중 하나는 여러 조건이 없다는 것입니다. if (else)에 대해 여러 조건을 가질 수 있지만 스위치에서 조건이 다른 여러 경우에는 적용 할 수 없습니다.
스위치 문은 간단한 부울 방정식 / 표현 범위를 벗어난 논리 연산에는 적합하지 않습니다. 부울 방정식 / 표현의 경우 다른 논리 연산에는 적합하지 않지만 적합합니다.
If 문에서 사용할 수있는 논리로는 훨씬 더 많은 자유가 있지만 If 문이 다루기 어려워 지거나 제대로 처리되지 않으면 가독성이 떨어질 수 있습니다.
둘 다 당신이 직면 한 상황에 따라 자리가 있습니다.