我观察到空合并运算符和 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() ?? false或emptyCollection?.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)
为什么是这样?这里发生了什么?我错过了什么?
根据运算符优先级,条件 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,您将看到所需的行为