if 条件中的隐式可空转换

Implicit nullable cast inside if condition

我最近发现了一些具有可为空 if 条件的代码,如下所示:

bool? nullableVariable;
//some lines of code involving nullableVariable
if (nullableVariable == true)
{
    //some other lines of code
}

乍一看,我认为它可能容易出现异常。我的意见基于以下事实:

bool? nullableVariable = null;
bool variable = (bool)nullableVariable

会引发错误 System.InvalidOperationException: 'Nullable object must have a value.' 我希望在 if (nullableVariable == true) 语句中从 [=15 转换左操作数=] 到 bool 将被执行(我的印象是在 == 运算符上移动光标会导致 Visual Studio 提示 bool bool.operator == (左布尔,右布尔)).

鉴于此,我很惊讶地看到:

bool? nullableVariable = null;
if (nullableVariable == true)
{
    //some other lines of code
}

不会引发异常(跳过括号内的代码)。

所以问题是:if 语句中发生了什么?可能是左操作数从 bool?bool 的隐藏 try-catch 转换,catch 将结果设置为 false?或者从 bool 转换为 bool? 的右操作数?还是别的?

lifted operators in Nullable value types

简而言之,它们对于像 ==:

这样的比较来说超载了

For the equality operator ==, if both operands are null, the result is true, if only one of the operands is null, the result is false; otherwise, the contained values of operands are compared.

因此,通过与 truefalse 进行比较,您可以避免处理可空值为 null 的情况,这使得代码更具可读性,如您的示例所示:

if (nullableVariable == true)
{
    //some other lines of code
}

因此,每当您比较(==!=bool?bool 时,结果都不是 bool?(或 null) 但 bool 具有上述 link 中描述的规则。这就是为什么您可以在 if.

中使用它的原因

正如其他人所提到的,相等运算符被提升为可为 null 的等价物。

它的编译方式似乎略有不同。我不完全确定为什么,但这可能与缺乏编译器知识有关运算符对复杂结构有副作用,而像 intbool 这样的类型它知道发生了什么。

然后 AB 可以为空,

A == B

针对 int 等基本类型,编译为以下内容:

(A.GetValueOrDefault() == B.GetValueOrDefault()) && (A.HasValue == B.HasValue)

对于更复杂的类型:

(A.HasValue == B.HasValue) ? !A.HasValue ||  (A.GetValueOrDefault() == B.GetValueOrDefault())