如何对布尔条件进行空合并?

How to null coalesce for Boolean condition?

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

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

但是条件有误:

Cannot implicitly convert 'bool?' to 'bool'. An explicit conversion exists (are you missing a cast?)

看来条件的计算结果为可为空的布尔值,所以我尝试

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

但这也不好:

'bool' does not contain a definition for 'Value' and no extension .... blah blah blah

所以在第一个实例中它抱怨它是一个可为空的布尔值,但在第二个实例中它抱怨它不是。

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

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

这有效 - 但它不应该,因为它使用了第一条消息说它不需要的隐式转换!

这是怎么回事?正确的做法是什么?

==可以和bool?对比一下,确实是best/simplest的做法:

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

至于为什么它在 if 中是不允许的,但是对于 ==Jon Skeet can explain 更好:

There's no implicit conversion from Nullable<bool> to bool. There is an implicit conversion from bool to Nullable<bool> and that's what happens (in language terms) to each of the bool constants in the first version. The bool operator==(Nullable<bool>, Nullable<bool>) operator is then applied. (This isn't quite the same as other lifted operators - the result is just bool, not Nullable<bool>).

In other words, the expression fred == false is of type bool, whereas the expression fred is of type Nullable<bool> hence you can't use it as the "if" expression.

所以 if 只允许 bool 而你有一个 bool?,但是 == 运算符将 bool 转换为 bool? 你可以比较两个 bool?.

编辑:

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

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

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

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

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

原文:

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

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

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

bool?.Value (属性) 这是 bool.

Any() returns bool 但是 Foo?.Any() 会 return bool?

因此 Foo?.Any().Value 不会编译,因为 Any() return 是一个没有成员 Valuebool

如果FoonullAny()将不会被执行,因为该语句将return null不解释[=后面的部分23=]运算符。

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

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

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

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