C# 分配布尔?哄骗

C# 分配布尔?哄骗,c#,.net,compiler-construction,nullable,C#,.net,Compiler Construction,Nullable,考虑以下代码: bool x; bool? y = null; x = y?? true; 将bool?分配给bool是编译时错误,但上述代码在编译时和运行时都成功。为什么?虽然第3条语句确保我们从不将null赋值给x,但如果y不是null,我们仍然将bool?赋值给bool,所以这应该是编译器的POV错误,不是 或者是C#编译器足够聪明,能够发现特定代码段不可能创建一种情况,将null分配给x?此表达式的类型: y ?? true 是bool,不是bool? 根据C#5规范第7.13节:

考虑以下代码:

bool x;
bool? y = null;
x = y?? true;
bool?
分配给
bool
是编译时错误,但上述代码在编译时和运行时都成功。为什么?虽然第3条语句确保我们从不将
null
赋值给
x
,但如果
y
不是null,我们仍然将
bool?
赋值给
bool
,所以这应该是编译器的POV错误,不是


或者是C#编译器足够聪明,能够发现特定代码段不可能创建一种情况,将
null
分配给
x

此表达式的类型:

y ?? true
bool
,不是
bool?

根据C#5规范第7.13节:

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

  • 如果存在且不是可空类型或引用类型,则会发生编译时错误
  • 如果
    b
    是动态表达式,则结果类型是动态的。在运行时,首先计算
    a
    。如果
    a
    不为空,
    a
    将转换为动态,这将成为结果。否则,
    b
    将被计算,这将成为结果
  • 否则,如果A存在并且是可空类型,并且存在从
    b
    到A0的隐式转换,则结果类型为A0。在运行时,首先计算
    a
    。如果
    a
    不为空,
    a
    将展开为A0类型,这将成为结果。否则,
    b
    将被计算并转换为A0类型,这将成为结果
  • 否则,如果存在A并且存在从
    b
    到A的隐式转换,则结果类型为A。在运行时,首先计算
    A
    。如果
    a
    不为空,
    a
    将成为结果。否则,
    b
    将被计算并转换为类型A,这将成为结果
  • 否则,如果
    b
    具有类型b并且存在从a到b的隐式转换,则结果类型为b。在运行时,首先计算
    a
    。如果
    a
    不为空,
    a
    将展开为A0类型(如果a存在且可为空),并转换为B类型,这将成为结果。否则,
    b
    将被计算并成为结果
  • 否则,
    a
    b
    不兼容,会发生编译时错误
在你的情况下,我们遇到了第三个问题:

  • A是
    bool?
  • A0是
    bool
  • B是
    bool
。。。因此,结果类型是
bool
,您可以将其分配给

bool x;
bool? y = null;
x = y?? true;
y??true
y.HasValue的语法糖吗?y、 GetValuerDefault():true
。因此,您实际上是在编译器的POV中分配一个
bool
。看看生成的IL,看看C#语言特性背后发生了什么


看一看。玩它会教你很多关于语言的知识

请参阅此链接的备注部分,您可以知道原因:

可为空的类型可以包含值,也可以是未定义的。这个 运算符定义当类型为可空时要返回的默认值 分配给不可为空的类型


你知道
??
操作员是干什么的吗?它的字面意思是“如果左侧为空,则使用右侧”。如果您将右侧设置为
bool?
也将不起作用。@ScottChamberlain:正确,但知道左侧是否为null只需在运行时确定。所以从编译器的角度来看,这难道不是一个错误吗?@ScottChamberlain:谢谢,伙计,我现在才看到。真不敢相信我居然没抓住要点。对于我们其他人来说,我上面的断言是不正确的,所以忽略它。我把它保存在这里作为历史。这里的要点是,整个RHS(
y??true
)是一个单独的表达式,它不是
bool?
(请参见Jon的答案以获得解释)类型。首先
y
在这里是第一位,不是吗?@MarcinJuraszek:对不起,说错了——尽管我解释得不对。编辑引用规范。难怪你是最有可能在2014年将你声誉中的“k”转换为“m”的人!谢谢你。