C# 空合并运算符与空集合和空集合之间的 OR 运算符结合时的行为不同

Jam*_*Law 3 c#

我观察到空合并运算符和 OR 运算符的一些奇怪行为,想知道是否有人可以对此有所了解。

var nullCollection = null as IEnumerable<string>;
var emptyCollection = Enumerable.Empty<string>();

Console.WriteLine(nullCollection?.Any() ?? false || true);
Console.WriteLine(emptyCollection?.Any() ?? false || true);
Run Code Online (Sandbox Code Playgroud)

产生以下输出:

True
False
Run Code Online (Sandbox Code Playgroud)

简单地评估nullCollection?.Any() ?? falseemptyCollection?.Any() ?? false同时评估yield False,这将是预期的行为,但将条件与||运算符似乎会导致不评估第二个条件,但仅在集合为空的情况下。

向空合并条件添加一些额外的括号似乎可以解决问题:

Console.WriteLine((nullCollection?.Any() ?? false) || true);
Console.WriteLine((emptyCollection?.Any() ?? false) || true);
Run Code Online (Sandbox Code Playgroud)

产量:

True
True
Run Code Online (Sandbox Code Playgroud)

为什么是这样?这里发生了什么?我错过了什么?

Pav*_*ski 9

根据运算符优先级,条件 OR 运算符的||优先级高于空合并运算符??

根据空合并运算符规范:

??如果左侧操作数的计算结果为非空,则运算符不会计算其右侧操作数。

因此,在您的代码中需要添加一个括号来使执行和??运算符评估的正确顺序。

没有括号 thisnullCollection?.Any()返回null,因此??运算符返回的结果false || true(由于优先级,如上所述),它总是true

emptyCollection?.Any()结果不是null并返回false,因此右侧false || true没有被评估,编译器足够聪明来理解它。

添加括号强制编译器执行运算符的预期执行:

  • (nullCollection?.Any() ?? false)返回,false因为左侧操作数是null,右侧操作数被执行。
  • (emptyCollection?.Any() ?? false)也返回false,左侧操作数null不执行,右侧不执行。

在这两种情况下false || true返回的逻辑 OR true,您将看到所需的行为