带有右侧三元表达式的布尔“或”不会短路

问题描述 投票:0回答:4

一般来说,如果左侧的计算结果为

||
,逻辑“或”运算符
true
的短路行为会忽略表达式的右侧。显然,使用三元作为右侧表达式是该规则的一个例外:

List<int> foo = null;
bool bar = false;

if (foo == null || bar != true ? foo.Count == 0 : true)
{
    // ...Conditional code...
}

此代码在

NullReferenceException
上抛出
foo.Count
,因为
foo
为空。当然,布尔逻辑允许这样做。但是,如果
foo
为空,您可能会期望“或”会短路,甚至不计算表达式的右侧,但它仍然如此,因此它会抛出异常。

这是我的代码或 C# 编译器中的错误吗? C# 规范中是否有部分可以处理这种情况?

c# .net short-circuiting logical-or
4个回答
17
投票

那是因为您的陈述没有按照您的预期进行评估。

您需要一些额外的括号:

if(foo == null || (bar != true ? foo.Count == 0 : true))

现在的写法相当于(由于运算符优先级):

if((foo == null || bar != true) ? foo.Count == 0 : true)    

11
投票

不,它可以正常工作,请参阅运算符优先级

||
将在
?:

之前进行评估

所以它首先评估

foo == null || bar != true
,然后评估
? foo.Count == 0 : true
,所以它更像是:

if ((foo == null || bar != true) ? foo.Count == 0 : true)
{

}

如果你想在这里使用短路那么应该是:

if (foo == null || (bar != true ? foo.Count == 0 : true))
{

}

3
投票

想象一下您正在检查的条件周围有括号:

if ((foo == null || bar != true) ? foo.Count == 0 : true)
{

}

因此,如果

foo
null
,则您正在尝试读取
foo.Count
,这自然会导致
NullReferenceException


2
投票

根据运算符优先级和结合性条件运算符

?:
具有最低优先级。因此它将最后执行。像这样:

(foo == null || bar != true) ? foo.Count == 0 : true
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.