使用空条件运算符检查可能为空的对象的值

Using the Null Conditional Operator to check values on objects which might be null

我一直在玩 C# 6 的 Null 条件运算符 (more info here)。

我真的很喜欢这种语法,我认为它使代码更具可读性,但是我认为当您检查 属性 的值时,代码究竟要做什么是值得怀疑的在本身可能为空的对象上。

例如,如果我有一个带有小数 属性 的 class 并且我想对该小数的值进行条件检查,我会这样写:

if (foo?.Bar > max)
{
   // do something
}

从表面上看,这看起来不错...如果 foo 不为空,获取 Bar 的值并检查它是否大于最大值,如果是,则执行某些操作。

但是,如果 foo 为 null 怎么办?!

This documentation about the new and improved features of C# 6 是这样说的:

if in fact the value of the object is null, the null-conditional operator will return null. It short-circuits the call to Bar, and immediately returns null, avoiding the programming error that would otherwise result in a NullReferenceException.

我已经写了一个 fiddle here 表明它确实有效并且正在做我期望它做的事情但是我无法理解它是怎么回事决定条件的结果。

短路怎么等于假?在我的脑海中,这段代码现在会说 "If foo is null, check if null is > max, which is impossible, so return false" 或 "If foo is null, then foo != null will return false, so you get a false" 但是文档说 null 条件检查 returns null,而不是 false。

How does the short-circuit equal a false?

if (foo?.Bar > max)
{
   // do something
}

roughly equivalent到:

Decimal? bar = null;
if (foo != null)
    bar = foo.Bar;

if (bar > max)
{
   // do something
}

因此,短路不等于false。它等于 Decimal?(可空 Decimal),与 max.

相比,它是 then

另请参阅:How does comparison operator works with null int?

It short-circuits the call to Bar

表示如果父对象已经为空,则停止检查对象引用链中的以下步骤 (.)。这意味着像比较这样的运算符不受影响,因为您 使用值 而不是 在链中移动 。这种行为称为空传播。您可以在 Code Project or Dave Fancher.

找到一些不错的描述

使用 null 条件运算符 returns 可以为 null 的值,例如 double?。然后将该值与 max 进行比较。 Microsoft:

很好地描述了 null 在这种比较中的行为

When you perform comparisons with nullable types, if the value of one of the nullable types is null and the other is not, all comparisons evaluate to false except for != (not equal).

这意味着:

if (null > max)
{
    //never called
}

Null Conditional Operator 应该只用于对象属性的多重赋值(参见对象映射等)的场景,如果出现 [=24= 的空条件,每次验证可能很无聊].

或者也适用于以下情况:

int? count = customers?[0]?.Orders?.Count();  // null if customers, the first customer, or Orders is null 

if 测试表达式中使用此运算符可能会导致意外行为,例如在您的 if statements case on fiddler 中您会得到一个 "passed" 测试(最后一个 if语句)但具有 null 值,这显然不是有效的情况