Почему сопоставление шаблонов с нулевым результатом в синтаксических ошибках?
Мне нравится использовать pattern-matching
в nullable int
т. nullable int
int?
:
int t = 42;
object tobj = t;
if (tobj is int? i)
{
System.Console.WriteLine($"It is a nullable int of value {i}");
}
Однако это приводит к следующим синтаксическим ошибкам:
"i)" помечено красной волнистой линией.
Выражение компилирует при использовании старого оператора is
:
int t = 42;
object tobj = t;
if (tobj is int?)
{
System.Console.WriteLine($"It is a nullable int");
}
string t = "fourty two";
object tobj = t;
if (tobj is string s)
{
System.Console.WriteLine([email protected]"It is a string of value ""{s}"".");
}
Также работает как положено.
(Я использую c#-7.2 и протестировал оба .net-4.7.1 и .net-4.6.1)
Я думал, что это связано с приоритетом оператора. Поэтому я пытался использовать скобки в нескольких местах, но это не помогло.
Почему он дает эти синтаксические ошибки и как их избежать?
Ответы
Ответ 1
Шаблон типа в его различных формах: x is T y
, case T y
т.д., Всегда не соответствует, когда x
равен null
. Это потому, что null
не имеет типа, поэтому спрашивает "это null
этого типа?" это бессмысленный вопрос.
Поэтому t is int? i
t is int? i
или t is Nullable<int> i
не имеет смысла в качестве шаблона: либо t
является целым int
, в этом случае t
является целым int
t is int i
все равно совпаду, либо оно равно null
, и в этом случае ни один шаблон типа не может привести к совпадению.
И это причина, почему t is int? i
t is int? i
or t is Nullable<int> i
Компилятор не поддерживает и, вероятно, никогда не поддержит его.
Причиной, по которой вы получаете дополнительные ошибки от компилятора при использовании t is int? i
t is int? i
из-за того, что, например, t is int? "it an int": "no int here"
t is int? "it an int": "no int here"
является допустимым синтаксисом, поэтому компилятор запутается из-за ваших попыток использовать ?
для обнуляемого типа в этом контексте.
Что касается того, как их можно избежать, то очевидный (хотя, вероятно, не очень полезный) ответ таков: не используйте обнуляемые типы в качестве типов в шаблонах типов. Более полезный ответ потребует от вас объяснить, почему вы пытаетесь это сделать.
Ответ 2
Измените свой код на:
int t = 42;
object tobj = t;
if (tobj is Nullable<int> i)
{
Console.WriteLine($"It is a nullable int of value {i}");
}
Это дает более полезную информацию:
- CS8116: Недействительно использовать тип "int?" с нулевым значением? в шаблоне; используйте базовый тип 'int' вместо (Не удалось найти документацию о CS8116 для ссылки)
Другие (пользователь @Blue0500 в github) отметили это поведение как ошибку Вопрос Roslyn № 20156. Реагирование на Вопрос Roslyn # 20156, Julien Couvreur от Microsoft сказал, что он думает, что это по дизайну.
Neal Gafter от Microsoft, работающего над Roslyn, также сказал
За исключением tobj is int? i
, это все еще оставляет вопрос, почему не разрешено tobj is int? i
или tobj is Nullable<int> i
.