【问题标题】:Using the Null Conditional Operator to check values on objects which might be null使用 Null 条件运算符检查可能为 null 的对象的值
【发布时间】:2017-08-21 12:03:04
【问题描述】:

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

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

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

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

表面上看起来很棒...如果 foo 不为 null,则获取 Bar 的值并检查它是否大于最大值,如果是,则执行一些操作。

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

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

如果实际上对象的值为空,则空条件 运算符将返回 null。它使对 Bar 的调用短路,并且 立即返回 null,避免编程错误 否则会导致 NullReferenceException。

我写了一个小提琴here,它表明它确实有效并且正在做我期望它做的事情,但是我无法理解它是如何决定条件结果的。

短路如何等于假?在我的脑海中,这段代码现在会说“如果 foo 为 null,检查 null 是否 > max,这是不可能的,所以返回 false”或“如果 foo 为 null,那么 foo != null 将返回 false,所以你得到a false" 但是文档说 null 条件检查返回 null,而不是 false。

【问题讨论】:

  • 有趣的是,无论条件是(bar > max)还是(bar <= max),它都不会运行do something。所以基本上,条件中的null 值将始终评估为false,无论实际条件是什么。
  • 如果 foo 为空,您应该使用 (foo?.Bar).GetValueOrDefault(2) 设置用于比较的值。我指定了“2”,但如果你省略参数,它默认为零。

标签: c# c#-6.0 null-conditional-operator


【解决方案1】:

短路如何等于假?

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相比然后

另见:How does comparison operator works with null int?

【讨论】:

  • 这是有道理的。文档说它返回 null 但这意味着它足够聪明,知道返回的 null 实际上是一个 nullable ,其值为 null ...有没有人反映了什么?。居然在内部做?
  • 点击我的帖子@DannyLager 中的链接。其中之一展示了罗斯林如何降低它。它基本上将?. 转换为我上面的东西(不完全相同,但足够接近)。
  • The documentation says it returns null 基本上,它需要返回一个特定类型null。鉴于Bar 属性是DecimalDecimal? 是显而易见的选择。
  • 谢谢 我看过第一个链接但不明白它是什么!第二个链接非常有趣,我不知道所有运算符(除了!=)都会以这种方式处理 null,尽管我过去从未遇到过这个问题!
  • @AkashKC 这是一个指向 Roslyn 源代码的链接,它降低了?.。至于降低是什么,请参阅stackoverflow.com/a/45772116/34092。你也可以喜欢阅读msdn.microsoft.com/en-us/magazine/…
【解决方案2】:

它使对 Bar 的调用短路

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

使用 null 条件运算符会返回一个可以为 null 的值,例如 double?。然后将该值与max 进行比较。 Microsoft 很好地描述了在这种比较中 null 的行为:

当您执行与可为空类型的比较时,如果值一 可空类型中的一个是 null 而另一个不是,所有比较 计算结果为 false,除了 !=(不等于)。

这意味着:

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

【讨论】:

    【解决方案3】:

    Null Conditional Operator 应仅用于与对象属性的多重分配有关的场景(请参阅对象映射等),在这种情况下,每次如果发生属性的 null 条件可能会很无聊。

    或者也适用于以下场景:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-12-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-06
      • 2021-06-17
      相关资源
      最近更新 更多