C # 스위치 명령문 제한-왜?


141

switch 문을 작성할 때 case 문에서 켤 수있는 항목에는 두 가지 제한이있는 것으로 보입니다.

예를 들어 (그렇습니다, 당신이 이런 종류의 일을하고 있다면 그것은 아마도 객체 지향 (OO) 아키텍처가 iffy라는 것을 의미합니다 -이것은 단지 고안된 예입니다!)

  Type t = typeof(int);

  switch (t) {

    case typeof(int):
      Console.WriteLine("int!");
      break;

    case typeof(string):
      Console.WriteLine("string!");
      break;

    default:
      Console.WriteLine("unknown!");
      break;
  }

여기서 switch () 문은 '정수 유형의 예상 값'으로 실패하고 사례 문은 '상수 값이 예상됩니다'로 실패합니다.

이러한 제한이 필요한 이유는 무엇이며 기본 정당성은 무엇입니까? switch 문 정적 분석에만 성공해야하는 이유와 켜져있는 값이 완전한 (즉, 기본) 이유를 알 수 없습니다. 정당화 란 무엇입니까?


1
가능한 해결 방법을 참조하십시오. '전환 유형'보다 더 나은 대안이 있습니까?
Michael Freidgeim

내장 유형을 켜는 또 다른 옵션은 TypeCode Enum 을 사용하는 것 입니다.
Erik Philips

간단히 ENUM을 생성하고 스위치의 경우 NameOf를 사용하십시오. 동적 변수에서 상수로 작동합니다.
Vaibhav.

답변:


99

이것은 ... 어떤 토론을 촉발 내 원래의 게시물입니다 잘못 때문에 :

switch 문은 큰 if-else 문과 동일하지 않습니다. 각 사례는 고유해야하며 정적으로 평가되어야합니다. switch 문은 보유한 사례 수에 관계없이 일정한 시간 분기를 수행합니다. if-else 문은 각 조건이 참일 때까지 각 조건을 평가합니다.


실제로 C # switch 문은 항상 일정한 시간 분기 가 아닙니다 .

어떤 경우에는 컴파일러가 CIL switch 문을 사용하는데, 이는 실제로 점프 테이블을 사용하여 일정한 시간 분기입니다. 그러나 Ivan Hamilton 이 지적한 드문 경우 에는 컴파일러가 완전히 다른 것을 생성 할 수 있습니다.

이것은 다양한 C # 스위치 문, 일부 희박하고 밀도가 높고 ildasm.exe 도구를 사용하여 결과 CIL을 보면 실제로 쉽게 확인할 수 있습니다.


4
다른 답변 (내 것을 포함하여)에서 언급 했듯이이 답변의 주장은 정확하지 않습니다. 삭제를 권장합니다 (이것은 아마도 일반적인 오해를 방지하기 위해).
mweerden

결론적으로 switch 문이 일정한 시간 분기를 수행한다는 것을 내 의견으로 보여주는 아래 게시물을 참조하십시오.
브라이언 Ensink

답장을 보내 주셔서 감사합니다, 브라이언 Ivan Hamilton의 답변을 참조하십시오 ((48259) [ beta.stackoverflow.com/questions/44905/#48259] ). 간단히 말해서 : C # 의 명령문과 동일하지 않은 (CIL의) switch 명령 에 대해 이야기하고 switch있습니다.
mweerden

컴파일러가 문자열을 켤 때 상수 시간 분기를 생성한다고 생각하지 않습니다.
Drew Noakes

C # 7.0의 스위치 케이스 명령문에서 패턴 일치에 여전히 적용 가능합니까?
B. Darren Olson

114

C # switch 문과 CIL switch 명령을 혼동하지 않는 것이 중요합니다.

CIL 스위치는 점프 테이블이므로 점프 주소 세트에 대한 색인이 필요합니다.

이것은 C # 스위치의 케이스가 인접한 경우에만 유용합니다.

case 3: blah; break;
case 4: blah; break;
case 5: blah; break;

그러나 그렇지 않은 경우 거의 사용하지 않습니다.

case 10: blah; break;
case 200: blah; break;
case 3000: blah; break;

(3 개의 슬롯 만 사용하여 ~ 3000 개의 테이블 크기 항목이 필요합니다)

인접하지 않은 표현식을 사용하면 컴파일러는 선형 if-else-if-else 검사를 수행하기 시작할 수 있습니다.

인접하지 않은 더 큰 표현식 세트를 사용하면 컴파일러는 이진 트리 검색으로 시작하여 마지막으로 몇 개의 항목 만 if-else-if-else로 시작할 수 있습니다.

인접한 항목의 덩어리를 포함하는 표현식 세트를 사용하면 컴파일러는 이진 트리 검색과 마지막으로 CIL 스위치를 사용할 수 있습니다.

이것은 "mays"& "mights"로 가득 차 있으며 컴파일러에 따라 다릅니다 (Mono 또는 Rotor와 다를 수 있음).

인접한 경우를 사용하여 결과를 컴퓨터에 복제했습니다.

10 웨이 스위치를 실행하는 총 시간, 10000 회 반복 (ms) : 25.1383
10 웨이 스위치 당 대략적인 시간 (ms) : 0.00251383

50 웨이 스위치를 실행하는 총 시간, 10000 회 반복 (ms) : 26.593
50 웨이 스위치 당 대략적인 시간 (ms) : 0.0026593

5000 웨이 스위치를 실행하는 총 시간, 10000 반복 (ms) :
5000 웨이 스위치 (ms) 당 대략적인 시간 : 23.7094 : 0.00237094

50000 웨이 스위치를 실행하는 총 시간, 10000 반복 (ms) : 205000 년
스위치 (ms) 당 대략적인 시간 : 0.00200933

그런 다음 인접하지 않은 케이스 표현식을 사용했습니다.

10 웨이 스위치를 실행하는 총 시간, 10000 회 반복 (ms) : 19.6189
10 웨이 스위치 당 대략적인 시간 (ms) : 0.00196189

500 웨이 스위치를 실행하는 총 시간, 10000 반복 (ms) : 19.1664
500 웨이 스위치 (ms) 당 대략적인 시간 : 0.00191664

5000 웨이 스위치를 실행하는 총 시간, 10000 반복 (ms) :
5000 웨이 스위치 (ms) 당 대략적인 시간 : 19.5871 : 0.00195871

인접하지 않은 50,000 개의 case switch 문은 컴파일되지 않습니다.
"표현식이 너무 길거나 복잡하여 'ConsoleApplication1.Program.Main (string [])'근처에서 컴파일 할 수 없습니다.

여기서 재미있는 점은 이진 트리 검색이 CIL 스위치 명령보다 약간 (통계적으로는 그렇지 않음) 빠르다는 것입니다.

Brian, " constant " 라는 단어를 사용했는데 , 이는 계산 복잡도 이론 관점에서 매우 명확한 의미를 갖습니다. 단순한 인접 정수 예제는 O (1) (일정)로 간주되는 CIL을 생성 할 수 있지만, 드문 예제는 O (log n) (대수)이며 군집 된 예제는 중간에 있고 작은 예제는 O (n) (선형)입니다. ).

이것은 정적을 Generic.Dictionary<string,int32>만들 수있는 String 상황을 다루지 않으며 처음 사용할 때 명확한 오버 헤드를 겪게됩니다. 여기서의 성능은의 성능에 따라 다릅니다 Generic.Dictionary.

CIL 사양이 아닌 C # 언어 사양 을 확인하면 "15.7.2 switch statement"에 "일정한 시간"에 대한 언급이 없거나 기본 구현에서 CIL 스위치 명령어를 사용하기도합니다 (매우 신중하게 가정해야 함). 그런 것들).

하루가 끝나면 현대 시스템의 정수 식에 대한 C # 스위치는 마이크로 초 미만의 작업이며 일반적으로 걱정할 필요가 없습니다.


물론이 시간은 기계와 조건에 따라 다릅니다. 이 타이밍 테스트에주의를 기울이지 않을 것입니다. 우리가 말하는 마이크로 초의 지속 시간은 실행중인 "실제"코드로 인해 난장이입니다 (그리고 "실제 코드"를 포함해야합니다. 그렇지 않으면 컴파일러가 분기를 최적화합니다). 시스템의 지터. 내 대답은 IL DASM 을 사용 하여 C # 컴파일러로 만든 CIL을 검사 한 결과입니다. 물론 CPU가 실행하는 실제 명령어는 JIT에 의해 생성되므로 최종적인 것은 아닙니다.

x86 컴퓨터에서 실제로 실행되는 최종 CPU 명령어를 확인했으며 다음과 같은 간단한 인접 세트 스위치를 확인할 수 있습니다.

  jmp     ds:300025F0[eax*4]

이진 트리 검색이 가득한 경우 :

  cmp     ebx, 79Eh
  jg      3000352B
  cmp     ebx, 654h
  jg      300032BB
  
  cmp     ebx, 0F82h
  jz      30005EEE

실험 결과가 약간 놀랍습니다. 브라이언과 교환 했습니까? 그의 결과는 크기에 따라 증가하지만 당신은 그렇지 않습니다. 뭔가 빠졌어? 어쨌든 명확한 답장을 보내 주셔서 감사합니다.
mweerden

이러한 작은 작업으로 타이밍을 정확하게 계산하는 것은 어렵습니다. 우리는 코드 나 테스트 절차를 공유하지 않았습니다. 인접한 사건에서 왜 그의 시간이 증가해야하는지 알 수 없습니다. 광산은 10 배 빠르므로 환경 및 테스트 코드가 크게 다를 수 있습니다.
Ivan Hamilton

23

가장 먼저 떠오르는 이유는 역사적입니다 .

대부분의 C, C ++ 및 Java 프로그래머는 이러한 자유를 얻는 데 익숙하지 않기 때문에 요구하지 않습니다.

또 다른 더 유효한 이유는 언어 복잡성이 증가 한다는 것입니다 .

우선, 객체 .Equals()==연산자를 비교해야 합니까? 두 경우 모두 유효합니다. 이를 위해 새로운 구문을 도입해야합니까? 프로그래머가 자체 비교 방법을 소개하도록 허용해야합니까?

또한 객체를 켤 수있게 하면 switch 문에 대한 기본 가정 집니다. 개체를 켤 수있는 경우 컴파일러에서 적용 할 수없는 switch 문에 적용되는 두 가지 규칙이 있습니다 ( C # 버전 3.0 언어 사양 , §8.7.2 참조).

  • 스위치 라벨의 값이 일정하다는 것을
  • 스위치 레이블의 값이 고유해야합니다 (따라서 주어진 스위치 표현에 대해 하나의 스위치 블록 만 선택할 수 있습니다)

상수가 아닌 경우 값이 허용되었다는 가설의 경우이 코드 예제를 고려하십시오.

void DoIt()
{
    String foo = "bar";
    Switch(foo, foo);
}

void Switch(String val1, String val2)
{
    switch ("bar")
    {
        // The compiler will not know that val1 and val2 are not distinct
        case val1:
            // Is this case block selected?
            break;
        case val2:
            // Or this one?
            break;
        case "bar":
            // Or perhaps this one?
            break;
    }
}

코드는 무엇을합니까? 사례 진술이 재정렬되면 어떻게됩니까? 실제로, C #이 스위치를 잘못 통과 한 이유 중 하나는 스위치 문을 임의로 재 배열 할 수 있기 때문입니다.

이러한 규칙은 이유가 있으므로 프로그래머는 하나의 사례 블록을보고 블록이 입력되는 정확한 조건을 알 수 있습니다. 위에서 언급 한 스위치 문이 100 줄 이상으로 커지면 그러한 지식은 매우 중요합니다.


2
스위치 순서 변경에 유의하십시오. 사건에 코드가없는 경우 추락은 합법적입니다. 사례 1 : 사례 2 : Console.WriteLine ( "Hi"); 단절;
Joel McBeth

10

그런데 동일한 기본 아키텍처를 가진 VB는 훨씬 더 유연한 Select Case명령문을 허용 하고 (위 코드는 VB에서 작동 할 수 있음) 이것이 가능한 경우 효율적인 코드를 생성하므로 기술적 제약 조건에 의한 인수를 신중하게 고려해야합니다.


1
Select Case엔 VB는 매우 유연하고 슈퍼 시간을 절약 할 수 있습니다. 많이보고 싶었습니다.
Eduardo Molteni

@EduardoMolteni 그러면 F #으로 전환하십시오. 파스칼과 VB의 스위치는 바보 아이처럼 보입니다.
Luaan

10

대부분 언어 디자이너 때문에 이러한 제한 사항이 적용됩니다. 근본적인 정당성은 언어 이력, 이상 또는 컴파일러 설계의 단순화와의 호환성 일 수 있습니다.

컴파일러는 다음을 수행 할 수 있습니다.

  • 큰 if-else 문을 작성하십시오
  • MSIL 스위치 명령어 사용 (점프 테이블)
  • Generic.Dictionary <string, int32>를 빌드하고 처음 사용할 때 채우고 인덱스가 MSIL 스위치 명령 (점프 테이블)에 전달되도록 Generic.Dictionary <> :: TryGetValue ()를 호출하십시오.
  • if-elses 및 MSIL "스위치"점프의 조합을 사용하십시오.

switch 문은 일정한 시간 분기가 아닙니다. 컴파일러는 단축키 (해시 버킷 사용 등)를 찾을 수 있지만 더 복잡한 경우 더 복잡한 MSIL 코드를 생성 할 수 있습니다.

String 경우를 처리하기 위해 컴파일러는 a.Equals (b) (및 가능하면 a.GetHashCode ())를 사용하여 (어느 시점에서) 끝납니다. 컴파일러가 이러한 제약 조건을 만족시키는 객체를 사용하는 것은 사소한 일이라고 생각합니다.

정적 케이스 표현식의 필요성에 관해서는 ... 케이스 표현식이 결정적이지 않은 경우 최적화 (해싱, 캐싱 등) 중 일부를 사용할 수 없습니다. 그러나 우리는 이미 컴파일러가 어쨌든 단순한 if-else-if-else 도로를 선택하는 것을 보았습니다 ...

편집 : lomaxx- "typeof"연산자에 대한 이해가 올바르지 않습니다. "typeof"연산자는 형식에 대한 System.Type 개체를 얻는 데 사용됩니다 (상위 형식이나 인터페이스와는 관련이 없음). 주어진 유형을 가진 객체의 런타임 호환성을 확인하는 것은 "is"운영자의 작업입니다. 여기서 "typeof"를 사용하여 객체를 표현하는 것은 관련이 없습니다.


6

Jeff Atwood에 따르면이 주제에 대해 switch 문은 프로그래밍 문제 입니다. 드물게 사용하십시오.

종종 테이블을 사용하여 동일한 작업을 수행 할 수 있습니다. 예를 들면 다음과 같습니다.

var table = new Dictionary<Type, string>()
{
   { typeof(int), "it's an int!" }
   { typeof(string), "it's a string!" }
};

Type someType = typeof(int);
Console.WriteLine(table[someType]);

7
증거없이 커프 트위터 게시물에서 누군가의 의견을 진지하게 인용하고 있습니까? 최소한 신뢰할 수있는 출처에 연결하십시오.
Ivan 해밀턴

4
신뢰할 수있는 출처에서 온 것입니다. 문제의 Twitter 게시물은보고있는 사이트의 작성자 인 Jeff Atwood의 것입니다. :-) Jeff는 궁금한 점이 있으면이 주제에 대한 블로그 게시물을 보유하고 있습니다.
유다 가브리엘 히 망고

제프 애트우드 (Jeff Atwood)가 글을 썼는지 여부에 관계없이 이것이 전체 BS라고 생각합니다. switch 문이 상태 머신을 처리하는 데 얼마나 적합한 지, enum유형 값에 따라 코드 흐름을 변경하는 다른 예는 재미 있습니다. enum유형 의 변수를 켤 때 intellisense가 자동으로 switch 문을 채우는 것은 우연의 일치가 아닙니다 .
Jonathon Reinhart 2018 년

@JonathonReinhart 그래, 그게 요점이라고 생각한다 switch. 문장을 사용하는 것보다 다형성 코드를 처리하는 더 좋은 방법이있다 . 그는 상태 머신을 작성해서는 안된다고 말하는 것이 아니라 멋진 특정 유형을 사용하여 동일한 작업을 수행 할 수 있다는 것입니다. 물론 F #과 같은 언어에서는 매우 복잡한 상태를 쉽게 처리 할 수있는 유형이 훨씬 더 쉽습니다. 예를 들어, 상태가 유형의 일부가되는 구별 된 공용체를 사용 switch하고 패턴 일치로 대체 할 수 있습니다. 또는 예를 들어 인터페이스를 사용하십시오.
Luaan

오래된 대답 / 질문이지만 (내가 틀렸다면 정정하십시오) Dictionary최적화 된 switch진술 보다 상당히 느릴 것이라고 생각했을 것입니다 ...?
Paul

6

switch 문이 정적 분석에만 의존 해야하는 이유는 없습니다.

사실, 그것은하지 않습니다 에, 많은 언어는 실제로 사용하는 동적 스위치 문에서 않습니다. 그러나 "case"절의 순서를 바꾸면 코드의 동작이 변경 될 수 있습니다.

여기에 "스위치"로 들어가는 디자인 결정 뒤에는 흥미로운 정보가 있습니다. 왜 C # 스위치 문이 폴 스루를 허용하지 않지만 여전히 중단이 필요하도록 설계 되었습니까?

동적 케이스 표현식을 허용하면 다음 PHP 코드와 같은 괴물이 생길 수 있습니다.

switch (true) {
    case a == 5:
        ...
        break;
    case b == 10:
        ...
        break;
}

솔직히 그 if-else진술을 사용해야합니다 .


1
그것이 내가 PHP에 대해 좋아하는 것입니다 (현재 C #으로 전환 할 때), 그것은 자유입니다. 그것으로 나쁜 코드를 작성하는 자유가 온다. 그러나 이것은 내가 C #에서 정말로 놓친 것이다
silkfire

5

마이크로 소프트는 마침내 당신을 들었다!

이제 C # 7을 사용하면 다음을 수행 할 수 있습니다.

switch(shape)
{
case Circle c:
    WriteLine($"circle with radius {c.Radius}");
    break;
case Rectangle s when (s.Length == s.Height):
    WriteLine($"{s.Length} x {s.Height} square");
    break;
case Rectangle r:
    WriteLine($"{r.Length} x {r.Height} rectangle");
    break;
default:
    WriteLine("<unknown shape>");
    break;
case null:
    throw new ArgumentNullException(nameof(shape));
}

3

이유는 아니지만 C # 사양 섹션 8.7.2에 다음과 같이 나와 있습니다.

스위치 문의 관리 유형은 스위치 식으로 설정됩니다. 스위치 표현식의 유형이 sbyte, byte, short, ushort, int, uint, long, ulong, char, string 또는 enum-type 인 경우 switch 문의 제어 유형입니다. 그렇지 않으면 스위치 식 유형에서 sbyte, byte, short, ushort, int, uint, long, ulong, char, string 중 하나로 가능한 하나의 사용자 정의 암시 적 변환 (§6.4)이 존재해야합니다. . 이러한 암시 적 변환이 존재하지 않거나 그러한 암시 적 변환이 둘 이상 존재하면 컴파일 타임 오류가 발생합니다.

C # 3.0 사양은 다음 위치에 있습니다. http://download.microsoft.com/download/3/8/8/388e7205-bc10-4226-b2a8-75351c669b09/CSharp%20Language%20Specification.doc


3

위의 유다의 대답은 나에게 아이디어를 주었다. 다음을 사용하여 위의 OP 스위치 동작을 "가짜"지정할 수 있습니다 Dictionary<Type, Func<T>.

Dictionary<Type, Func<object, string,  string>> typeTable = new Dictionary<Type, Func<object, string, string>>();
typeTable.Add(typeof(int), (o, s) =>
                    {
                        return string.Format("{0}: {1}", s, o.ToString());
                    });

이를 통해 동작을 switch 문과 동일한 스타일의 유형과 연결할 수 있습니다. IL로 컴파일 할 때 스위치 스타일 점프 테이블 대신 키가 추가되는 이점이 있다고 생각합니다.


0

컴파일러가 switch 문을 자동으로 변환 할 수없는 근본적인 이유가 없다고 생각합니다.

if (t == typeof(int))
{
...
}
elseif (t == typeof(string))
{
...
}
...

그러나 그것에 의해 많이 얻지는 않습니다.

정수 유형에 대한 case 문을 사용하면 컴파일러에서 여러 가지 최적화를 수행 할 수 있습니다.

  1. 중복이 없습니다 (컴파일러가 감지하는 대소 문자 레이블을 복제하지 않는 한). 귀하의 예에서 t는 상속으로 인해 여러 유형과 일치 할 수 있습니다. 첫 경기가 실행되어야합니까? 그들 모두?

  2. 컴파일러는 모든 비교를 피하기 위해 점프 테이블에 의해 정수 유형에 대해 switch 문을 구현하도록 선택할 수 있습니다. 정수 값이 0-100 인 열거를 켜는 경우 각 switch 문마다 하나씩 100 개의 포인터가있는 배열을 만듭니다. 런타임에 단순히 켜져있는 정수 값을 기준으로 배열에서 주소를 찾습니다. 이는 100 번의 비교를 수행하는 것보다 훨씬 더 나은 런타임 성능을 제공합니다.


1
여기서 주목해야 할 중요한 복잡성이 있다는 것입니다 .NET의 메모리 모델은 (가상 무효로 정확하게 동일하지 귀하의 의사 수 있도록 특정 강력한 보장이 C # .NET을 ) switch (t) { case typeof(int): ... }번역은 그 변수가 의미하기 때문에 t 있어야 두 번 경우 메모리에서 인출 할 수 t != typeof(int)있는 반면, 후자는 것, (가상적으로) 항상 t 정확히 한 번의 값을 읽습니다 . 이러한 차이로 인해 우수한 보증에 의존하는 동시 코드의 정확성이 깨질 수 있습니다. 이에 대한 자세한 정보를 원하시면, 조 더피의 볼 Windows에서 동시 프로그래밍
글렌 Slayden

0

스위치 명령문 문서 에 따르면 오브젝트를 내재적으로 완전한 유형으로 변환하는 명확한 방법이 있으면 허용됩니다. 각 사례에 대해로 대체되는 동작을 기대하고 if (t == typeof(int))있지만 해당 연산자에 과부하가 걸리면 전체 웜이 열립니다. == 재정의를 잘못 쓴 경우 switch 문의 구현 세부 사항이 변경되면 동작이 변경됩니다. 정수형과 문자열에 대한 비교와 정수형으로 축소 될 수있는 (및 의도 된) 것들을 비교함으로써 잠재적 인 문제를 피할 수 있습니다.


0

쓴 :

"Switch 문은 사례 수에 관계없이 일정한 시간 분기를 수행합니다."

이 언어는 문자열 유형을 스위치 문에 사용할 수 있기 때문에 컴파일러 가이 유형에 대한 일정 시간 분기 구현을위한 코드를 생성 할 수 없으며 if-then 스타일을 생성해야한다고 가정합니다.

@mweerden-아 알 겠어. 감사.

C # 및 .NET에 대한 경험이 많지 않지만 언어 디자이너는 좁은 환경을 제외하고 유형 시스템에 대한 정적 액세스를 허용하지 않는 것 같습니다. 과 typeof 이 실행 시간 만에 액세스 할 수 있도록 키워드는 개체를 반환합니다.


0

헨크가 "타입 시스템에 접근 할 수 없다"고 생각했습니다.

다른 옵션은 숫자와 문자열이 될 수있는 유형에 순서가 없다는 것입니다. 따라서 유형 스위치는 이진 검색 트리를 만들 수 없으며 선형 검색 만 할 수 있습니다.


0

테이블 기반 접근 방식을 사용하는 것이 더 낫다는 이 의견에 동의합니다 .

C # 1.0에서는 제네릭과 익명 대리자가 없기 때문에 불가능했습니다. 새 버전의 C #에는이 작업을 수행하기위한 스캐 폴딩이 있습니다. 객체 리터럴에 대한 표기법도 도움이됩니다.


0

나는 C #에 대한 지식이 거의 없지만 스위치를 다른 언어로 만들 때 더 일반적으로 생각하지 않고 단순히 다른 언어로 발생했거나 개발자가 확장 할 가치가 없다고 결정했다고 생각합니다.

엄밀히 말하면 이러한 제한을 적용 할 이유가 없다는 것이 절대적으로 옳습니다. 그 이유는 허용 된 경우에 대해 구현이 매우 효율적이라고 생각할 수 있지만 (Brian Ensink ( 44921 )에서 제안한 대로 ) 정수 및 임의의 경우를 사용하면 구현이 매우 효율적이라고 생각합니다 (wrt if 문) (예 : 345, -4574 및 1234203). 그리고 어쨌든 모든 (또는 적어도 이상)에 대해 허용하고 특정 경우 (예 : 연속)와 같은 경우에만 효과적이라고 말하는 것은 어떤 해를 끼칩니다.

그러나 lomaxx ( 44918 ) 와 같은 이유로 유형을 제외하고 싶을 수도 있습니다 .

편집 : @Henk ( 44970 ) : 문자열이 최대로 공유되면 내용이 같은 문자열도 동일한 메모리 위치에 대한 포인터가됩니다. 그런 다음 사례에 사용 된 문자열이 메모리에 연속적으로 저장되도록 할 수 있으면 스위치를 매우 효율적으로 구현할 수 있습니다 (예 : 2 개의 비교, 더하기 및 2 개의 점프 순서로 실행).


0

C # 8에서는 스위치 식을 사용하여이 문제를 우아하고 간결하게 해결할 수 있습니다.

public string GetTypeName(object obj)
{
    return obj switch
    {
        int i => "Int32",
        string s => "String",
        { } => "Unknown",
        _ => throw new ArgumentNullException(nameof(obj))
    };
}

결과적으로 다음을 얻습니다.

Console.WriteLine(GetTypeName(obj: 1));           // Int32
Console.WriteLine(GetTypeName(obj: "string"));    // String
Console.WriteLine(GetTypeName(obj: 1.2));         // Unknown
Console.WriteLine(GetTypeName(obj: null));        // System.ArgumentNullException

새 기능에 대한 자세한 내용은 여기를 참조하십시오 .

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