16

快速的问题在这里关于C#中的短路语句。如果这样的语句是这样的:短路声明评估 - 是否有保证? [C#]

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

//.... 
} 

确保在“MyArray.Count”部分之后停止评估,前提是该部分为真?否则,我会在第二部分中得到一个空例外。

+1

如果你问这个问题是因为你从上面的代码中得到了一个空引用异常,那很可能是因为MyArray是null或者MyArray [0]包含null。看到我的答案。 – 2010-04-22 16:26:20

回答

34

是的,这是有保证的。

C# Language Specification - 7.11 Conditional logical operators

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

因此他们会支持逻辑短路顾名思义- 你可以依赖于这种行为。

现在做出条件运营商和逻辑运营商之间的区别是很重要的:

  • 只有有条件的运营商支持短路,逻辑运算符不。
  • C#的逻辑运算符看起来就像它们的条件对应项,但少一个字符,因此逻辑OR为|,逻辑AND为&
  • 逻辑运算符可能被重载,但条件运算符不能(这是一个技术性问题,因为条件运算符评估确实涉及重载解析,并且此重载解析可以解析为该类型逻辑运算符的自定义重载,所以您可以解决此问题限制在一定程度上)。
+1

+1用于实际引用CLS。 – Polynomial 2012-10-08 15:31:03

5

是的,它是有保证的,但你仍然可以得到一个空引用异常,如果MYARRAY为空(或为MyObject为此事很明显)。

0

我更喜欢使用& &操作,因为你再测试阳性(我的数组包含的项目),而不是消极的(我的错误不包含的项目):

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

//.... 
} 

这也保证短路。

+0

虽然这段代码的结果与他不一样。在他的,如果计数为0,它短路并进入块。在你的,它*只*进入块的第一个元素的值为0. – 2010-04-22 15:43:32

2

只是一个小小的观察。

你说的这个:

否则我将在第二部分得到空例外。 (重点是我的)

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

仍然可能你可以得到一个NullReferenceException,如果你对象中的第一个项目实际上是零(或如果任何在表达其他对象都是)。

唯一完全安全检查将是这样的:

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

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

如果(!conditionHolds) – riffnl 2010-04-22 16:33:52

+0

@riffnl:我只是让我的例子与OP的代码一致。 (他/她似乎希望代码在否定的情况下做一些事情。) – 2010-04-22 16:37:13

2

是,

并操作,如果任何操作数的评估,以评估为假,则有假,则总的表达不需要评估剩余的表达式,并且在OR操作的情况下,如果任何操作数评估为真,则剩余的评估可以被跳过

因此,通过使用& &或||运算符,整个表达式可以评估为true或false,而不必评估所有的子表达式。

但也考虑它的side effect也。 This article可能有助于深入了解短路评价与一些真实世界的例子。