在 C# 8 中,为什么对新表达式的类型推断会导致可空引用?

Mic*_*ell 2 c# c#-8.0 nullable-reference-types

如果我有 C# 8 代码:

class Foo {}
Run Code Online (Sandbox Code Playgroud)

然后:

#nullable enable
var bar = new Foo();
Run Code Online (Sandbox Code Playgroud)

那么 的类型barFoo?。这显然不正确,因为new表达式不能返回null。为什么会bar是一个可为空的引用?我什至查阅了Nullable Reference Type Specification,发现了以下内容:

永远不为空的表达式

以下表达式形式的空状态始终为“非空”:

  • ...
  • new 表达式(对象、委托、匿名对象和数组创建表达式)
  • ...

并且:

var 的类型推断

为用 var 声明的局部变量推断的类型由初始化表达式的空状态通知。

var x = E;
Run Code Online (Sandbox Code Playgroud)

如果类型E是可空的引用类型C?和空状态E是“不空”,则推断该类型xC。否则,推断的类型是 的类型E

推断的类型的可空性x如上所述确定,基于 的注释上下文var,就像在该位置明确给出类型一样。

因此,根据我在规范中可以找到的所有内容,bar在我非常简单的示例中,应该是 type Foo,而不是 type Foo?。我错过了什么?

Jul*_*eur 8

如果var要从表达式推断其可空性,那么在许多情况下,您以后将无法为其分配 a null。例如,var s = "";。有一次讨论允许var?表达“类型的可为空版本”,但它有几个问题。常规var是否会被限制为推断不可为空的类型?

如果是,那么 (1) 我们正在创建采用痛苦,因为用户需要添加更多?注释,(2) 我们与var已经发布的模式不一致的可空性,(3) 有一些关于可空值类型 ( int?) 的问题。如果不是,那么代码的意图就不是很清楚。var?将清楚地指示可空类型,但var将是可空和不可空的混合包。

2019 年 12 月 18 日varLDM 说明中记录了推断可空类型的决定。

  • 因此,如果您想声明不可为空的引用(并且这种情况比可为空的引用更频繁地发生),则需要使用显式类型(var!可能是一个选项,不是吗?)……我不明白这样做的好处在哪里不能再使用隐式声明... (4认同)
  • 好答案。我确实不同意这个逻辑,但我至少知道它来自哪里。 (2认同)