考虑以下代码:
bool x;
bool? y = null;
x = y?? true;
将
bool?
分配给 bool
是编译时错误,但上述代码在编译时和运行时均成功。为什么?虽然第三条语句确保我们永远不会将null
分配给x
,但如果y
不为空,我们仍然将bool?
分配给bool
,所以这应该是编译器POV的错误,没有?
或者 C# 编译器是否足够聪明,能够发现某段特定的代码不可能创建将
null
分配给 x
的情况?
该表达式的类型:
y ?? true
是
bool
,不是bool?
。
摘自 C# 5 规范第 7.13 节:
表达式
的类型取决于操作数上可用的隐式转换。按照优先顺序,a ?? b
的类型为A0、A或B,其中A是a的类型(假设a有一个类型),B是b的类型(假设b有一个类型)类型),如果 A 是可为 null 的类型,则 A0 是 A 的基础类型,否则是 A。具体来说,a ?? b
的处理如下:a ?? b
- 如果 A 存在并且不是可为空类型或引用类型,则会发生编译时错误。
- 如果
是动态表达式,则结果类型是动态的。在运行时,首先评估b
。如果a
不为 null,则a
转换为动态,这就是结果。否则,将评估a
,这将成为结果。b
- 否则,如果 A 存在且可为 null 类型,并且存在从
到 A0 的隐式转换,则结果类型为 A0。在运行时,首先评估b
。如果a
不为空,则将a
展开为类型 A0,这将成为结果。否则,将计算a
并将其转换为类型 A0,这将成为结果。b
- 否则,如果 A 存在并且存在从
到 A 的隐式转换,则结果类型为 A。在运行时,首先评估b
。如果a
不为空,则a
成为结果。否则,计算a
并转换为类型 A,这就是结果。b
- 否则,如果
具有类型 B 并且存在从 a 到 B 的隐式转换,则结果类型为 B。在运行时,首先评估b
。如果a
不为 null,则a
被展开为类型 A0(如果 A 存在且可为空)并转换为类型 B,这将成为结果。否则,将评估a
并成为结果。b
- 否则,
和a
不兼容,会出现编译时错误。b
就您而言,我们处于第三个项目符号中:
bool?
bool
bool
...所以结果类型是
bool
,您可以将其分配给 bool
类型的变量。
在
bool x;
bool? y = null;
x = y?? true;
y ?? true
是 y.HasValue ? y.GetValueOrDefault() : true
的语法糖。所以你实际上是在编译器的 POV 中分配了一个 bool
。查看生成的 IL,了解 C# 语言功能背后发生了什么。
ILDasm
。玩它会教你很多关于语言的知识!
请参阅此链接的备注部分,您就可以知道原因: http://msdn.microsoft.com/en-us/library/vstudio/ms173224.aspx
可空类型可以包含值,也可以是未定义的。这 ?? 运算符定义可空类型时要返回的默认值 被分配给不可为 null 的类型