переключатель с 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 соответствует on case var o
?
насколько я понимаю,case string s
не совпадает, когда s == null
потому что (фактически) (null as string) != null
принимает значение false. IntelliSense на VS Code говорит мне, что o
это string
как хорошо. Есть мысли?
аналогично: C# 7 switch case с нулевыми проверками
3 ответа:
внутри шаблона
switch
заявление с помощьюcase
для явного типа задает вопрос, Является ли рассматриваемое значение этого конкретного типа или производным типом. Это точный эквивалентis
switch (someString) { case string s: } if (someString is string)
значение
null
не имеет типа и, следовательно, не удовлетворяет ни одному из вышеперечисленных условий. Статический типsomeString
не вступает в игру ни в одном примере.The
var
тип, хотя в сопоставлении шаблонов действует как дикая карта и будет соответствовать любому значению в том числеnull
.The
default
случай вот мертвый код. Элементcase var o
будет соответствовать любому значению, null или non-null. Нестандартный случай всегда выигрывает по умолчанию, следовательно,default
никогда не будет хитом. Если вы посмотрите на IL, вы увидите, что он даже не испускается.на первый взгляд может показаться странным, что это компилируется без предупреждения (определенно сбил меня с толку). Но это соответствует поведению C#, которое восходит к 1.0. Компилятор позволяет
default
случаи, даже когда он может тривиально доказать, что он никогда не будет поражен. Рассмотрим в качестве примера следующее:bool b = ...; switch (b) { case true: ... case false: ... default: ... }
здесь
default
никогда не будет поражен (даже дляbool
которые имеют значение, которое не является 1 или 0). Тем не менее, C# разрешил это с 1.0 без предупреждения. Сопоставление с образцом-это просто падение в соответствии с этим поведение.
я собираю несколько комментариев twitter здесь - это на самом деле ново для меня, и я надеюсь, что jaredpar будет прыгать с более полным ответом, но; короткая версия, как я понимаю:
case string s:
трактуется как
if(someString is string) { s = (string)someString; ...
илиif((s = (someString as string)) != null) { ... }
- каждый из которых включает в себяnull
тест-который не удалось в вашем случае; наоборот:case var o:
где компилятор
o
какstring
простоo = (string)someString; ...
- нет