将bool?分配给bool

3

Consider the following code:

bool x;
bool? y = null;
x = y?? true;

bool?赋值给bool是一个编译时错误,但是上面的代码在编译和运行时都成功了。为什么?虽然第三个语句确保我们永远不会将null分配给x,但是如果y不为null,我们仍然将bool?分配给bool,所以从编译器的角度来看,这应该是一个错误,不是吗?
还是说C#编译器足够聪明,能够找到一段代码不可能创建一个null被分配给x的情况?

6
你知道 ?? 运算符是什么吗?它的意思是“如果左边为空,则使用右边”。如果你也将右边设为 bool?,它将不起作用。 - Scott Chamberlain
@ScottChamberlain:没错,但是左侧是否为空只能在运行时确定。所以从编译器的角度来看,这仍然应该是一个错误吗? - dotNET
@ScottChamberlain:谢谢,伙计,我现在才看到。真不敢相信我怎么会错过这个要点。对于我们其他人来说,我上面的断言是不正确的,所以请忽略它。我将其保留在这里作为历史记录。这里的要点是整个 RHS (y?? true) 是一个单一表达式,它不会是 bool? 类型(请参见 Jon 的答案以获取解释)。 - dotNET
3个回答

2

这个表达式的类型:

y ?? true

bool 的类型是 bool,而不是 bool?

来自 C# 5 规范的第 7.13 节:

表达式 a ?? b 的类型取决于操作数上可用的隐式转换。按优先顺序,a ?? b 的类型为 A0、A 或 B,其中 A 是 a 的类型(前提是 a 有一个类型),B 是 b 的类型(前提是 b 有一个类型),A0 是 A 的基础类型,如果 A 是可空类型,则为其基础类型;否则为 A。具体而言,a ?? b 如下处理:

  • 如果 A 存在且不是可空类型或引用类型,则会发生编译时错误。
  • 如果 b 是动态表达式,则结果类型为 dynamic。运行时,首先计算 a。如果 a 不为 null,则将其转换为 dynamic,并成为结果。否则,计算 b,并成为结果。
  • 否则,如果 A 存在且是可空类型,并且存在从 b 到 A0 的隐式转换,则结果类型为 A0。运行时,首先计算 a。如果 a 不为 null,则将其解包为类型 A0,并成为结果。否则,计算 b,并将其转换为类型 A0,并成为结果。
  • 否则,如果 A 存在且存在从 b 到 A 的隐式转换,则结果类型为 A。运行时,首先计算 a。如果 a 不为 null,则成为结果。否则,计算 b,并将其转换为类型 A,并成为结果。
  • 否则,如果 b 具有类型 B,并且存在从 a 到 B 的隐式转换,则结果类型为 B。运行时,首先计算 a。如果 a 不为 null,则将其解包为类型 A0(如果 A 存在且可空),并转换为类型 B,并成为结果。否则,计算 b,并作为结果。
  • 否则,ab 不兼容,并发生编译时错误。

在您的情况下,我们处于第三个项目符号:

  • A 是 bool?
  • A0bool
  • B 是 bool

...因此结果类型为bool,您可以将其分配给类型为bool的变量。


首先?这里是以 y 为首的,对吧? - MarcinJuraszek
@MarcinJuraszek:抱歉,方向错了——虽然我也解释得不正确。编辑以引用规范中的内容。 - Jon Skeet
难怪你是2014年最有可能将你声望中的“k”转化为“m”的人!非常感谢。 - dotNET

1

bool x;
bool? y = null;
x = y?? true;

y ?? truey.HasValue ? y.GetValueOrDefault() : true 的语法糖。因此,在编译器的视角下,您实际上是在分配一个 bool。查看生成的 IL 以了解 C# 语言特性背后发生的事情。

看一眼 ILDasm。与它玩耍会让您对语言有更多的了解!


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接