[c#] var / null 이상한 동작으로 전환

다음 코드가 주어집니다.

string someString = null;
switch (someString)
{
    case string s:
        Console.WriteLine("string s");
        break;
    case var o:
        Console.WriteLine("var o");
        break;
    default:
        Console.WriteLine("default");
        break;
}

switch 문이 일치하는 이유는 무엇 case var o입니까?

(효과적으로) 거짓으로 평가 되기 때문에 case string s일치하지 않는 것은 내 이해입니다 . VS 코드에 대한 인텔리는 나에게 말한다 A는 뿐만 아니라. 이견있는 사람?s == null(null as string) != nullostring


유사 항목 : Null 검사가있는 C # 7 스위치 케이스



답변

명시 적 유형에 대해를 switch사용 하는 패턴 일치 문 내 case에서 문제의 값이 특정 유형인지 파생 된 유형인지 묻습니다. 정확히 동일합니다.is

switch (someString) {
  case string s:
}
if (someString is string) 

null에 유형이 없으므로 위의 조건을 충족하지 않습니다. 정적 유형은 someString두 예 모두에서 작동하지 않습니다.

var패턴 일치하지만 유형은 와일드 카드 역할을하며 포함한 모든 값과 일치합니다 null.

default여기 의 경우는 데드 코드입니다. 는 case var onull 또는 null이 아닌 모든 값과 일치합니다. 기본이 아닌 경우는 항상 기본 사례보다 우선하므로 default절대 적중되지 않습니다. IL을 보면 방출되지 않는 것을 볼 수 있습니다.

언뜻보기에 이것이 경고없이 컴파일된다는 것이 이상하게 보일 수 있습니다 (확실히 나를 버렸습니다). 그러나 이것은 1.0으로 돌아가는 C # 동작과 일치합니다. 컴파일러는 default절대 적중되지 않는다는 것을 사소하게 증명할 수있는 경우에도 케이스를 허용 합니다. 다음을 예로 고려하십시오.

bool b = ...;
switch (b) {
  case true: ...
  case false: ...
  default: ...
}

여기서는 default절대 히트 bool하지 않습니다 (1 또는 0이 아닌 값이있는 경우에도 ). 그러나 C #은 1.0부터 경고없이 이것을 허용했습니다. 패턴 매칭은 여기서이 동작과 일치합니다.


답변

여기에 여러 개의 트위터 댓글을 모으고 있습니다. 이것은 실제로 저에게 새로운 것이며, jaredpar가보다 포괄적 인 답변으로 뛰어 들기를 바라고 있습니다. 내가 이해하는 짧은 버전 :

case string s:

귀하의 경우에 실패한 if(someString is string) { s = (string)someString; ...또는 if((s = (someString as string)) != null) { ... }null테스트 를 포함하는 것으로 해석됩니다 . 거꾸로:

case var o:

여기서 컴파일러 결의 ostring단순히 o = (string)someString; ...– 어떤 null시험 에도 불구하고 단지 유형을 제공하는 컴파일러로, 표면에 비슷 사실.

드디어:

default:

위의 경우가 모든 것을 포착하기 때문에 여기에 도달 할 수 없습니다 . 도달 할 수없는 코드 경고를 표시하지 않았다는 점에서 컴파일러 버그 일 수 있습니다.

나는 이것이 매우 미묘하고 미묘하며 혼란 스럽다는 데 동의합니다 . 그러나 분명히 case var o시나리오는 널 전파 ( o?.Length ?? 0등) 와 함께 사용됩니다 . 나는 이것이 와 사이에서 매우 다르게 작동한다는 것이 이상하다는 데 동의 하지만 현재 컴파일러가하는 일입니다.var ostring s


답변

정적 (컴파일 타임) 유형이 아니라 동적 (런타임) 유형에서 case <Type>일치 하기 때문 입니다. 동적 유형이 없으므로 . 그냥 폴백입니다.nullstringvar

(짧은 답변을 좋아하기 때문에 게시합니다.)


답변