C#에서 if/else를 사용하는 것과 switch-case를 사용하는 것 사이에 큰 차이가 있습니까?
를 사용할 경우의 이점/단점은 무엇입니까?switch
대 진술if/else
C#에 있습니다. 코드 모양 외에는 그렇게 큰 차이가 있을 수 없습니다.
결과 IL 또는 관련 런타임 성능이 근본적으로 다를 이유가 있습니까?
관련:문자열을 켜는 것과 유형을 켜는 것 중 어떤 것이 더 빠릅니까?
SWITCH 문은 디버깅 또는 호환성 모드의 IF와 동일한 어셈블리만 생성합니다.릴리즈에서는 (MSIL 'switch' 문을 통해) 점프 테이블로 컴파일되며, 이는 O(1)입니다.
C#(다른 많은 언어와 달리)도 문자열 상수를 켤 수 있으며, 이는 약간 다르게 작동합니다.임의의 길이의 문자열에 대해 점프 테이블을 구축하는 것은 분명히 실용적이지 않으므로 대부분의 경우 이러한 스위치는 IF 스택으로 컴파일됩니다.
그러나 조건의 수가 오버헤드를 커버할 수 있을 정도로 크면 C# 컴파일러는 HashTable 개체를 만들고 문자열 상수로 채우고 해당 테이블을 검색한 다음 점프를 수행합니다.해시 테이블 룩업은 엄밀하게 O(1)가 아니며 눈에 띄는 일정한 비용을 가지고 있지만, 사례 레이블의 수가 많은 경우 IF의 각 문자열 상수와 비교하는 것보다 훨씬 더 빠릅니다.
요약하자면, 조건 수가 5개 이상인 경우에는 IF보다 SWITCH를 선호하고, 그렇지 않은 경우에는 더 좋아 보이는 것을 사용합니다.
일반적으로 (모든 언어와 모든 컴파일러를 고려할 때) if/other 문보다 스위치 문이 더 효율적일 수 있습니다. 컴파일러가 스위치 문에서 점프 테이블을 생성하는 것이 쉽기 때문입니다.적절한 제약 조건이 주어지면 if/other 문에 대해 동일한 작업을 수행할 수 있지만, 이는 훨씬 더 어렵습니다.
C#의 경우에도 마찬가지이지만 다른 이유가 있습니다.
문자열 수가 많으면 컴파일러가 점프를 구현하기 위해 해시 테이블을 사용하기 때문에 스위치 문을 사용하는 것에 상당한 성능 이점이 있습니다.
현의 수가 적으면 둘 사이의 연주는 같습니다.
이 경우 C# 컴파일러가 점프 테이블을 생성하지 않기 때문입니다.대신 IF / ELSE 블록에 해당하는 MSIL을 생성합니다.
jit할 때 점프 테이블을 사용하여 스위치 문을 구현하는 "스위치 문" MSIL 지침이 있습니다.그러나 정수 유형에서만 작동합니다(이 질문은 문자열에 대해 묻습니다).
문자열 수가 적을 경우 컴파일러가 IF / ELESS 블록을 생성하는 것이 해시 테이블을 사용하는 것보다 더 효율적입니다.
처음에 이것을 알았을 때, 저는 IF / ELES 블록이 소수의 문자열과 함께 사용되었기 때문에 컴파일러가 많은 문자열에 대해 동일한 변환을 수행했다고 가정했습니다.
이것은 틀렸습니다.IMA'는 친절하게도 제게 이것을 지적해 주었습니다.그는 그것에 대해 친절하지 않았지만, 그가 옳았고, 내가 틀렸습니다. 중요한 부분입니다.)
저는 또한 MSIL에 "스위치" 명령어가 없다는 것에 대해 뼈있는 가정을 했습니다. (스위치 프리미티브가 있다면, 왜 그들은 해시 테이블과 함께 사용하지 않았기에 스위치 프리미티브가 없어야 한다고 생각했습니다...)이것은 잘못되었고, 제 입장에서는 믿을 수 없을 정도로 어리석었습니다.IMA'는 다시 한 번 저에게 이것을 지적했습니다.
가장 높은 평가를 받은 게시물이기 때문에 여기에 업데이트를 했고, 승인된 답변입니다.
하지만,저는 제가 틀렸다는 이유로 REP를 받을 자격이 없다고 생각하기 때문에 커뮤니티 위키를 만들었습니다.기회가 된다면 'ima' 게시물에 투표해주세요.
컴파일러는 거의 모든 것을 사소한 차이로 동일한 코드로 최적화할 것입니다(Knuth, 아무나?).
차이점은 다른 문장들이 함께 나열된 경우 스위치 문장이 15보다 깨끗하다는 것입니다.
친구들은 친구들이 if-else 문을 쌓지 못하게 합니다.
▁▁to▁prefer▁를 선호하는 세 가지 이유switch
:
네이티브 코드를 대상으로 하는 컴파일러는 종종 스위치 문을 하나의 조건부 분기와 간접 점프로 컴파일할 수 있지만, 반면에 시퀀스는
if
s에는 일련의 조건부 분기가 필요합니다.사례의 밀도에 따라 사례 진술을 효율적으로 컴파일하는 방법에 대해 많은 학습된 논문이 작성되었습니다. 일부는 lcc 컴파일러 페이지에서 링크됩니다.(Lcc는 스위치용으로 보다 혁신적인 컴파일러 중 하나였습니다.)스위치 문은 상호 배타적인 대안 중 하나이며 스위치 구문은 이 제어 흐름을 프로그래머에게 더 투명하게 만들고 if-then-else 문의 둥지로 만듭니다.
ML 및 해스켈을 포함한 일부 언어에서는 컴파일러가 사용자가 누락한 사례가 있는지 확인합니다.저는 이 기능이 ML과 Haskell의 주요 장점 중 하나라고 생각합니다.C#가 이걸 할 수 있을지 모르겠어요.
한 일화: 평생 공로상을 수상한 강연에서 토니 호어가 자신의 경력에서 한 모든 일들 중에서 가장 자랑스러운 세 가지가 있다고 말하는 것을 들었습니다.
- Quicksort 발명
- 스테이트먼트가 스위치스트먼트를테가것이것르(토니 부는는하명발ton를▁the))라고 불렀던)를 한 것.
case
에 의거) - 산업 분야에서 경력을 시작하고 끝냅니다.
없이 사는 것은 상상할 수 없습니다.
사실, 스위치 문이 더 효율적입니다.컴파일러는 이를 룩업 테이블로 최적화하는 반면 if/else 문에서는 이를 최적화할 수 없습니다.단점은 스위치 문을 변수 값과 함께 사용할 수 없다는 것입니다.
할 수 없습니다.
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
}
대
switch(x) {
case 0:
// do one thing
break;
case 1:
// do the other thing
break;
case 2:
// do the third thing
break;
}
x가 0 90%인 경우, "if-else" 코드는 스위치 기반 코드보다 두 배 더 빠를 수 있습니다.컴파일러가 "스위치"를 일종의 교묘한 테이블 구동 바둑으로 바꾼다고 해도, 그것은 여전히 단순히 0을 확인하는 것만큼 빠르지 않을 것입니다.
종종 더 좋아 보일 것입니다. 즉, 무슨 일이 일어나고 있는지 이해하기가 더 쉬울 것입니다.성능상의 이점은 기껏해야 극히 미미할 것이라는 점을 고려할 때, 코드의 관점이 가장 중요한 차이입니다.
따라서 if/else가 더 좋아 보이면 사용하고, 그렇지 않으면 switch 문을 사용합니다.
. ( 더 봅니다.)if
/else
그리고.switch
문이 너무 커져서 케이스가 너무 많습니다.이로 인해 유지 관리가 어려워지는 경우가 많습니다.
일반적인 범인은 다음과 같습니다.
- 다중 if 문 내부에서 너무 많은 작업을 수행
- 인간이 분석할 수 있는 것보다 더 많은 사례 진술
- if 평가의 조건이 너무 많아 무엇을 찾고 있는지 알 수 없습니다.
수정 방법:
- 방법 리팩토링에 추출합니다.
- 대소문자 대신 메서드 포인터가 있는 사전을 사용하거나 추가 구성을 위해 IoC를 사용합니다.방법 공장도 도움이 될 수 있습니다.
- 고유한 방법으로 조건 추출
if 또는 other 문을 사용하는 경우 기본 솔루션은 비교 연산자를 사용합니다.
(value == value1) ? (type1)do this : (type1)or do this;
스위치에서 또는 루틴을 수행할 수 있습니다.
switch(typeCode)
{
case TypeCode:Int32:
case TypeCode.Int64:
//dosomething here
break;
default: return;
}
이 링크에 따르면 스위치와 if 문을 사용한 반복 테스트의 IF 대 스위치 비교는 1,000,000,000회 반복과 같습니다. Switch Statement = 43.0s 및 if Statement = 48.0s에서 소요되는 시간
말 그대로 초당 20833333회 반복입니다. 그래서 우리는 정말 더 집중해야 합니다.
추신: 작은 조건 목록에 대한 성능 차이를 알고 싶습니다.
이것은 실제로 당신의 질문에 대한 답은 아니지만, 컴파일된 버전 간에 거의 차이가 없을 것이기 때문에, 당신의 의도를 가장 잘 설명하는 방식으로 코드를 작성할 것을 권장합니다.컴파일러가 당신이 기대하는 것을 할 가능성이 더 높을 뿐만 아니라, 다른 사람들이 당신의 코드를 더 쉽게 유지할 수 있게 해줄 것입니다.
하나의 변수/속성 값을 기준으로 프로그램을 분기하려면 스위치 문이 해당 의도를 가장 잘 나타냅니다.
다른 변수/속성/조건을 기준으로 프로그램을 분기하려는 경우 if/else 체인이 해당 의도를 가장 잘 나타내는지 여부를 나타냅니다.
나는 사람들이 브레이크 명령을 잊어버린 것에 대해 코디가 옳다는 것을 인정하겠지만, 거의 자주 사람들이 {}을(를) 잘못 이해한 블록에서 복잡한 행동을 하는 것을 볼 수 있으므로 조건문에 있어야 하는 행은 그렇지 않습니다.행이 하나라도 if 문에 항상 {}을(를) 포함시키는 이유 중 하나입니다.읽기 쉬울 뿐만 아니라, 조건부로 한 줄을 더 추가해야 할 경우 잊지 않고 추가합니다.
관심 질문.몇 주 전에 회사에서 이 문제가 발생했습니다. 샘플 스니펫을 작성하여 .NET Reflector에서 확인함으로써 해결책을 찾았습니다. (Reflector는 훌륭합니다!!)너무 좋아요).
다음과 같이 확인했습니다. 문자열 이외의 모든 항목에 대한 유효한 스위치 문이 IL에 스위치 문으로 컴파일됩니다.그러나 문자열인 경우 IL에서 if/else로 다시 작성됩니다.따라서 우리의 경우 스위치 문이 대소문자를 구분하는 등 문자열을 비교하는 방법을 알고 싶었고 반사기가 신속하게 답을 주었습니다.이것은 알아두면 유용했습니다.
문자열에 대해 대소문자를 구분하여 비교하려면 문자열을 수행하는 것보다 더 빠르기 때문에 스위치 문을 사용할 수 있습니다.if/else로 비교합니다. (편집: 읽기 더 빠른 것은 무엇입니까, 문자열을 켜는 것입니까, 아니면 if를 켜는 것입니까?일부 실제 성능 테스트의 경우)그러나 대소문자를 구분하지 않으려면 if/else를 사용하는 것이 좋습니다. 왜냐하면 결과 코드가 예쁘지 않기 때문입니다.
switch (myString.ToLower())
{
// not a good solution
}
가장 좋은 경험 규칙은 다음과 같은 경우에 (심각하게) 의미가 있는 경우 스위치 문을 사용하는 것입니다.
- 코드의 가독성을 향상시킵니다.
- 값 범위(숫자, int) 또는 열거형을 비교하는 경우
스위치 문에 입력할 값을 조작해야 하는 경우(전환할 임시 변수 생성) if/else control 문을 사용해야 합니다.
업데이트:
실제로는 문자열을 대문자로 변환하는 것이 좋습니다(예:ToUpper()
) 그것이 명백했기 때문에 Just-in-Time 컴파일러가 할 수 있는 추가적인 최적화가 있습니다.ToLower()
이는 미세 최적화이지만, 엄격한 루프에서는 유용할 수 있습니다.
간단한 참고 사항:
스위치 문의 가독성을 향상시키려면 다음을 시도합니다.
- 가장 가능성이 높은 분기를 먼저 지정합니다. 즉, 가장 많이 액세스됨
- 모두 발생할 가능성이 있는 경우, 찾기 쉽도록 알파벳 순으로 나열합니다.
- 마지막 남은 조건에 대해 기본 catch-all을 사용하지 마십시오. 이는 게으르고 나중에 코드 수명에 문제가 발생합니다.
- 알 수 없는 조건이 발생할 가능성이 매우 낮더라도 기본 catch-all을 사용하여 알 수 없는 조건을 주장합니다.그것이 주장이 좋은 이유입니다.
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 및 동등성 검정을 계산할 필요가 없다고 암묵적으로 말하고 있기 때문입니다.
switch 문은 if가 아닌 경우보다 확실히 빠릅니다.BlackWasp에서 제공한 속도 테스트가 있습니다.
http://www.blackwasp.co.uk/SpeedTestIfElseSwitch.aspx
--확인해보세요.
그러나 설명하려는 가능성에 따라 크게 달라지지만, 가능할 때마다 스위치 문을 사용하려고 합니다.
제 2센트입니다.대부분의 경우 성능이 기준이 아니라 코드 가독성에 대한 것입니다.if/else 문 수가 switch 문을 사용하는 것보다 많으면 더 좋습니다.
나의 cs 교수님은 사람들이 너무 자주 휴식 시간을 잊거나 잘못 사용하기 때문에 당신에게 진술을 바꾸지 말라고 제안했습니다.나는 그가 정확히 무슨 말을 했는지 기억할 수 없지만 (몇 년 전) 스위치 문의 예를 보여주는 중요한 코드 기반을 보는 것은 그 안에도 많은 실수가 있었습니다.
방금 깨달은 것은 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;
}
다음과 같은 프로그램이 있는지 확인하는 것과 같은 경우보다 스위치가 더 빠르다고 생각합니다.
프로그램을 작성하여 1~99 사이의 숫자를 입력하고 a) 1~9번 슬롯, b) 11~19번 슬롯, c) 21~29번 슬롯, 89~99번 슬롯, 3번 슬롯이 어느 슬롯에 있는지 확인합니다.
많은 조건을 만들어야 하지만 손 전환 케이스를 입력해야 하는 경우에는 On.
스위치(no /10)
케이스 0 = 1-9, 케이스 1 = 11-19 등입니다.
아주 쉬울 것입니다
그러한 예들도 더 많이 있습니다!
스위치 문은 기본적으로 동일성에 대한 비교입니다.키보드 이벤트는 코드를 쉽게 쓰고 읽을 수 있을 때 스위치 문에 비해 큰 이점이 있으며, 그렇지 않을 경우 {dump}을(를) 누락하는 것도 문제가 될 수 있습니다.
char abc;
switch(abc)
{
case a: break;
case b: break;
case c: break;
case d: break;
}
if else if 문은 (사과의 양이 5보다 크고 사과의 양이 10보다 작음) 사과를 판매하는 경우 둘 이상의 솔루션에 대해 유용합니다(사과의 양이 10보다 큼 | | 사과의 양 == 100).나는 c#이나 c++를 쓰지 않지만 자바를 배우기 전에 그것을 배웠으며 그들은 가까운 언어입니다.
스위치 문의 한 가지 가능한 단점은 여러 조건이 없다는 것입니다.if(기타)에 대해 여러 조건을 가질 수 있지만 스위치 내에서 조건이 다른 여러 사례 문은 가질 수 없습니다.
스위치 문은 단순한 부울 방정식/식의 범위를 벗어나는 논리 연산에 적합하지 않습니다.이러한 부울 방정식/식의 경우 매우 적합하지만 다른 논리 연산에는 적합하지 않습니다.
If 문에서 사용할 수 있는 논리를 사용하면 훨씬 자유롭지만 If 문이 다루기 어렵거나 잘못 처리되면 가독성이 저하될 수 있습니다.
둘 다 당신이 직면한 상황에 따라 자리가 있습니다.
제 앞에 있는 모든 답변을 읽고 웹을 검색한 후에, 스위치 케이스 설명이 코드를 더 깔끔하고 관리하기 쉽게 만드는 데 도움이 될 것이라고 말할 수 있습니다.그리고 제가 프로젝트에서 테스트했을 때 10건 이상의 사례를 확인해야 하기 때문에(이상하게 들릴 수도 있습니다!) 다른 것보다 성능이 더 좋습니다.
언급URL : https://stackoverflow.com/questions/395618/is-there-any-significant-difference-between-using-if-else-and-switch-case-in-c
'sourcecode' 카테고리의 다른 글
iPhone/iPad의 UI 레이블에서 굵고 기울임꼴로 설정하려면 어떻게 해야 합니까? (0) | 2023.05.23 |
---|---|
도움말()이 메서드 서명을 나열하는 경우 슬래시는 무엇을 의미합니까? (0) | 2023.05.23 |
bash에서 변수의 줄 수를 계산하려면 어떻게 해야 합니까? (0) | 2023.05.23 |
Node.js에서 "ReferenceError: primaryials is not defined"를 수정하는 방법 (0) | 2023.05.23 |
angular-cli server - API 요청을 다른 서버로 프록시하는 방법은 무엇입니까? (0) | 2023.05.23 |