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

问题描述 投票:12回答:2

我喜欢在pattern-matching上使用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($@"It is a string of value ""{s}"".");
}

也按预期工作。

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

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

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

c# pattern-matching nullable c#-7.0
2个回答
15
投票

各种形式的类型模式:x is T ycase T y等,always fails to match when x is null。这是因为null doesn't have a type,所以问“这是这种类型的null吗?”是一个毫无意义的问题。

因此t is int? it is Nullable<int> i没有任何意义作为一种模式:tint,在这种情况下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"是有效的语法,因此编译器对您在此上下文中使用?作为可空类型的尝试感到困惑。

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


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 at github)已将此行为标记为bug Roslyn issue #20156。针对Roslyn issue #20156的反应,来自微软的Julien Couvreur表示他认为这是设计上的。 来自微软工作的Rosz的Neal Gafter也说过better diagnostics are wanted for use of nullable type is switch pattern

因此,使用以下命令可以避免错误消息:

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}");
}

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

© www.soinside.com 2019 - 2024. All rights reserved.