【问题标题】:How to null coalesce for Boolean condition?如何对布尔条件进行空合并?
【发布时间】:2017-12-23 03:12:02
【问题描述】:

我正在尝试安全地检查 IList<> 是否不为空。

var Foo = Bar.GimmeIListT(); // Returns an IList<SomeObject>
if (Foo?.Any())
    // Do cool stuff with items in Foo

但是条件有错误:

不能隐式转换 'bool?' '布尔'。存在显式转换(您是否缺少演员表?)

所以看起来条件评估为可以为空的布尔值,所以我尝试

if (Foo?.Any().Value())

但这也不好:

'bool' 不包含 'Value' 的定义,也没有扩展名...... blah blah blah

所以在第一种情况下它抱怨它是一个可为空的布尔值,但在第二种情况下它抱怨它不是。

作为我尝试的另一种途径:

if (Foo?.Any() == true)

这行得通 - 但它不应该因为这使用了第一条消息说它不想要的隐式转换!

发生了什么事?这样做的正确方法是什么?

【问题讨论】:

  • if (Foo?.Count > 0) { }
  • @AndzejMaciusovic:这是个坏方法。如果Foo 实际上是一个需要数小时才能完全执行的查询,您将严重错过Any。如果您想知道是否至少有一个,请不要全部计算。
  • @TimSchmelter 在我的示例中,我使用的是 .Count 而不是 Count()。Count 已经是 IList 上的计算字段,实际上使用 .Count 而不是 .Any() 会更快一些。在名单上。
  • @AndzejMaciusovic:是的,但是人们通常会理解这是一种好方法,而忽略了缺少的括号(在 VB.NET 中它们是可选的)。

标签: c# null-coalescing-operator


【解决方案1】:

如果您使用==,您可以与bool? 进行比较,这确实是最好/最简单的方法:

if (Foo?.Any() == true) ...

至于为什么在 if 中不允许使用它,但使用 ==Jon Skeet can explain 会更好:

没有从Nullable&lt;bool&gt;bool 的隐式转换。有 从boolNullable&lt;bool&gt; 的隐式转换就是这样 发生(在语言方面)第一个中的每个 bool 常量 版本。布尔运算符==(Nullable&lt;bool&gt;, Nullable&lt;bool&gt;) 运算符 然后应用。 (这与其他提升运算符不太一样 - 结果只是 bool,而不是 Nullable&lt;bool&gt;)。

换句话说,表达式fred == false 的类型是bool, 而表达式fredNullable&lt;bool&gt; 类型,因此你 不能用它作为“if”表达式。

所以if 只允许bool 并且您有一个bool?,但== 运算符将bool 转换为bool?,您可以比较两个bool?

【讨论】:

  • OP 已经尝试过这个这行得通 - 但它不应该因为这使用了第一条消息说它不想要的隐式转换!
  • @Pikoh:已修复 :)
  • 使用@JonSkeet 卡吧? :) 对,现在它确实解释了,+1
【解决方案2】:

更多的语法糖,空合并运算符。 C# 8.0 或更高版本

if (Foo?.Any() ?? false) { }

【讨论】:

    【解决方案3】:

    Any() 返回 boolFoo?.Any() 将返回 bool?

    所以Foo?.Any().Value 不会编译,因为Any() 返回一个没有成员Valuebool

    如果Foonull,则不会执行Any(),因为该语句将返回null,而不解释?. 运算符后面的部分。

    但是如果你把Foo?.Any()放在括号里,你可以使用bool?类型的结果并通过ValueGetValueOrDefault()检查它:

    (Foo?.Any()).GetValueOrDefault()
    

    【讨论】:

      【解决方案4】:

      编辑

      似乎bool? 的原因是Foo?.Any() 本身。如果你不想和true比较,我建议你有临时变量:

      bool? any = Foo?.Any(); 
      if (any.Value) ...
      

      或者,如果对象是一个类,您可以使用FirstOrDefault() != null 作为检查条件。它不会花费时间,因为它只会获取第一个对象:

      if (Foot?.FirstOrDefault() != null)...
      

      我将使用临时变量或Foo?.Any() == true 选项。

      原创

      注意:令我惊讶的是,if (a?.Any()) 后面不能跟 .Value().Value(!)。

      我认为你需要的是Value(属性)没有()(方法):

      if (Foo?.Any()?.Value) ... 
      

      bool? 具有.Value(属性),即bool

      【讨论】:

        猜你喜欢
        • 2013-04-12
        • 1970-01-01
        • 1970-01-01
        • 2020-08-16
        • 2019-10-24
        • 2019-03-12
        • 2014-05-01
        • 1970-01-01
        • 2013-12-02
        相关资源
        最近更新 更多