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