переключатель с 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для явного типа задает вопрос, Является ли рассматриваемое значение этого конкретного типа или производным типом. Это точный эквивалентisswitch (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; ...- нет