Nullable<bool> 的 null 否定

Rek*_*ino 1 c# compiler-errors logical-operators

null在否定 .c#的值的情况下,我对 c# 编译器感到困惑bool?。编译器确实将其解释!nullnull. 我的期望是提高

CS0266(无法将类型“bool?”隐式转换为“bool”)

示例代码:

bool? nullableVal = null;

//if (nullableVal)  //OK: CS0266 bool? can't be converted to bool
//    ;
var expectCS0266 = !nullableVal;//No compiler error/warning

//if ((!null) ?? false)//OK: CS8310 Operator '!' cannot be applied to operands of type "<NULL>"
//    ;

if (! nullableVal ?? false)
    ;//this statement isn't reached, because of precedence of ! is higher than ??
    //and !null == null

if (!(nullableVal ?? false))
    ;//this statement is reached, OK
Run Code Online (Sandbox Code Playgroud)

有人可以证明为什么编译器是正确的,反之亦然。

can*_*on7 6

请参阅规范第 7.3.7 节:

提升运算符允许对不可为空值类型进行操作的预定义和用户定义运算符也可以与这些类型的可空形式一起使用。提升运算符由满足特定要求的预定义运算符和用户定义运算符构造而成,如下所述:

  • 对于一元运算符,
        + ++ - -- ! ~
    如果操作数和结果类型都是不可空值类型,则存在运算符的提升形式。?提升形式是通过向操作数和结果类型添加单个修饰符来构造的。如果操作数为 null,则提升运算符会生成 null 值。否则,提升的运算符将解包操作数,应用底层运算符,并包装结果。

(强调我的)

所以:

bool? x = null;
bool? y = !x;
Run Code Online (Sandbox Code Playgroud)

遵循这个规则。我们使用一元运算符的提升形式!,这会导致null它所应用的值是否为null

!null不允许,因为null不是 type Nullable<T>!(bool?)null但是可以工作(尽管它会产生编译器警告)。

!确实具有比 更高的优先级??,请参见第 7.3.1 节

  • 我会将其标记为 __“如果操作数为空,则提升的运算符将生成空值”__ 粗体。感谢您对规格的报价! (2认同)