关于条件运算符:短路语句评估 – 这是否有保证?

Short circuiting statement evaluation — is this guaranteed? [C#]

这里是关于C中的短路声明的快速问题。用这样的if语句:

1
2
3
4
5
if (MyObject.MyArray.Count == 0 || MyObject.MyArray[0].SomeValue == 0)
{

//....
}

如果"myarray.count"部分为真,是否保证在该部分之后停止计算?否则,我将在第二部分中得到一个空异常。


是的,这是有保证的。

C语言规范-7.11条件逻辑运算符:

The && and || operators are called the conditional logical operators. They are also called the"short-circuiting" logical operators.

因此,根据定义,它们将支持逻辑短路-您可以依赖于此行为。

现在,区分条件运算符和逻辑运算符很重要:

  • 只有条件运算符支持短路,逻辑运算符不支持。
  • C的逻辑运算符看起来像它们的条件对应符,但少了一个字符,所以逻辑OR是|,逻辑AND是&
  • 逻辑运算符可以重载,但条件运算符不能重载(这有点技术性,因为条件运算符计算确实涉及重载解决方案,而此重载解决方案可以解析为类型逻辑运算符的自定义重载,因此可以在一定程度上解决此限制)。


是的,这是有保证的。

http://msdn.microsoft.com/en-us/library/6373h346%28v=vs.80%29.aspx

The conditional-OR operator (||) performs a logical-OR of its bool operands, but only evaluates its second operand if necessary.


是的,这是有保证的,但是如果myArray为空(或者显然是myObject),您仍然可以获得空引用异常。


对,

For AND operations if any of the operand evaluated to false then total expression evaluated to false then there is no need to evaluate remaining expressions, And in case of OR operation if any of the operand evaluated to true then remaining evaluation can be skipped

因此,通过使用&;&;或运算符,可以在不计算所有子表达式的情况下将整个表达式计算为true或false。

但也要考虑它的副作用。本文结合一些实际案例,对深入理解短路评估有一定的帮助。


只是一个小小的观察。

你这样说:

Otherwise I'll get a null exception in the second part. (emphases mine)

事实上,这不是真的。如果不能保证短路,你可以在第二部分得到一个IndexOutOfRangeException

如果您的MyArray对象中的第一个项实际上为空(或者如果表达式中的任何其他对象为空),您仍然可以获得NullReferenceException

唯一完全安全的检查是:

1
2
3
4
5
6
7
8
9
10
11
bool conditionHolds =
    MyObject == null ||
    MyObject.MyArray == null ||
    MyObject.MyArray.Count == 0 ||
    MyObject.MyArray[0] == null ||
    MyObject.MyArray[0].SomeValue == 0;

if (conditionHolds)
{
    //....
}


我更喜欢使用&;运算符,因为您随后测试的是正数(我的数组包含项),而不是负数(我的错误不包含项):

1
2
3
4
5
if (MyObject.MyArray.Count > 0 && MyObject.MyArray[0].SomeValue == 0)
{

//....
}

这也保证了短路。