为什么可以为空的模式匹配会导致语法错误?

Kas*_*erg 15 c# nullable pattern-matching c#-7.0

我喜欢pattern-matchingnullable intie 上使用int?:

int t  = 42;
object tobj = t;    
if (tobj is int? i)
{
    System.Console.WriteLine($"It is a nullable int of value {i}");
}
Run Code Online (Sandbox Code Playgroud)

但是,这会导致以下语法错误:

'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($@"It is a string of value ""{s}"".");
}
Run Code Online (Sandbox Code Playgroud)

也按预期工作.

(我正在使用并使用进行测试)

我认为它与运算符优先级有关.因此,我尝试在几个地方使用括号,但这没有帮助.

为什么会出现这些语法错误,如何避免这些错误呢?

Dav*_*rno 16

各种形式的类型模式:x is T y,case T y等,总是匹配失败时xnull.这是因为null没有类型,所以问"这null是这种类型吗?" 是一个毫无意义的问题.

因此t is int? it is Nullable<int> i作为模式没有任何意义:要么t是一个int,在这种情况下无论如何t is int i都匹配,或者它是null,在这种情况下,没有类型模式可以导致匹配.

这就是编译器支持t is int? it is Nullable<int> i不支持的原因,也可能永远不会支持.

您在使用时从编译器获得其他错误的原因t is int? i是由于例如t is int? "it's an int" : "no int here"有效语法这一事实,因此编译器对您?在此上下文中使用可空类型的尝试感到困惑.

至于如何避免它们,明显(尽管可能不是很有帮助)的答案是:不要使用可空类型作为类型模式中的类型.更有用的答案需要您解释为什么要尝试这样做.


Kas*_*erg 6

将您的代码更改为:

int t = 42;
object tobj = t;
if (tobj is Nullable<int> i)
{
    Console.WriteLine($"It is a nullable int of value {i}");
}
Run Code Online (Sandbox Code Playgroud)

这会产生更有帮助的:

  • CS8116:使用可空类型“int”是不合法的?在一个模式中;改用基础类型“int” (找不到有关 CS8116 的文档以供参考)

其他人(github 上的用户@Blue0500)已将此行为标记为错误Roslyn 问题 #20156。针对Roslyn 问题 #20156 的反应,来自微软的Julien Couvreur表示他认为这是设计使然。来自 Microsoft 从事 Roslyn 工作的
Neal Gafter也表示,对于可空类型是 switch 模式的使用,需要更好的诊断

因此,可以使用以下方法避免错误消息:

int t = 42;
object tobj = t;
if (tobj == null)
{
    Console.WriteLine($"It is null");
}
else if (tobj is int i)
{
    Console.WriteLine($"It is a int of value {i}");
}
Run Code Online (Sandbox Code Playgroud)

除了解析时问题tobj is int? i,这仍然留下了为什么允许tobj is int? itobj is Nullable<int> i不允许的问题。

  • 我猜在您的问答中的所有样本中,`t is` 应该是 `tobj is` (2认同)