短路语句评估——这有保证吗? [C#]

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

这里有一个关于 C# 中短路语句的快速问题。使用这样的 if 语句:

if (MyObject.MyArray.Count == 0 || MyObject.MyArray[0].SomeValue == 0)
{

//....
}

如果“MyArray.Count”部分为真,是否保证评估将停止?否则我会在第二部分得到一个空异常。

c# conditional-operator logical-operators short-circuiting
6个回答
37
投票

是的,这是有保证的。

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

&&
||
运算符称为条件逻辑运算符。 它们也称为“短路”逻辑运算符。

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

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

  • 只有条件运算符支持短路,逻辑运算符不支持。
  • C# 的逻辑运算符看起来就像条件运算符,但少了一个字符,因此逻辑 OR 为
    |
    ,逻辑 AND 为
    &
  • 逻辑运算符可以重载,但条件运算符不能(这有点技术性,因为条件运算符评估确实涉及重载解析,并且此重载解析可以解析为类型逻辑运算符的自定义重载,因此您可以解决此限制一定程度上)。

12
投票

是的,有保证。

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

条件或运算符 (||) 对其布尔操作数执行逻辑或,但仅在必要时计算其第二个操作数。


5
投票

是的,这是有保证的,但是如果 MyArray 为 null(显然是 MyObject),您仍然可以获得空引用异常。


2
投票

只是一个小小的观察。

你这样说:

否则我会在第二部分得到null异常。 (强调我的)

实际上这不是真的。如果不能保证短路,您可能会在第二部分中得到

IndexOutOfRangeException

如果 NullReferenceException 对象中的第一项实际上为空(或者该表达式中的任何

other
对象为空),那么
仍然
可能会得到 MyArray

唯一完全安全的检查是:

bool conditionHolds =
    MyObject == null ||
    MyObject.MyArray == null ||
    MyObject.MyArray.Count == 0 ||
    MyObject.MyArray[0] == null ||
    MyObject.MyArray[0].SomeValue == 0;

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

2
投票

是的,

对于 AND 运算,如果任何操作数评估为 false,则总表达式评估为 false,则无需评估其余表达式,而在 OR 运算的情况下,如果任何操作数评估为 true,则可以跳过剩余评估

所以通过使用 && 或 ||运算符,整个表达式可以计算为 true 或 false,而不需要计算所有子表达式。

但也要考虑它的副作用。 本文可能有助于通过一些现实世界的示例深入理解短路评估。


-1
投票

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

if (MyObject.MyArray.Count > 0 && MyObject.MyArray[0].SomeValue == 0) 
{ 

//.... 
} 

这也保证了短路。

© www.soinside.com 2019 - 2024. All rights reserved.