短路声明评估 – 这有保证吗?

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

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

是否保证评估将在“MyArray.Count”部分后停止,前提是该部分为真? 否则我会在第二部分得到一个nullexception。

是的,这是有保证的。

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

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

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

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

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

是的,这是有保证的。

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

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

是的,它是有保证的,但是如果MyArray为null(或者显然是MyObject),你仍然可以得到一个空引用exception。

只是一个小小的观察。

你说的这个:

否则我会在第二部分得到一个nullexception 。 (强调我的)

实际上,事实并非如此。 如果无法保证短路,则可以在第二部分中获得IndexOutOfRangeException

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

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

 bool conditionHolds = MyObject == null || MyObject.MyArray == null || MyObject.MyArray.Count == 0 || MyObject.MyArray[0] == null || MyObject.MyArray[0].SomeValue == 0; if (conditionHolds) { //.... } 

是,

对于AND操作,如果任何操作数计算为false,则总表达式计算为false,则不需要评估剩余表达式。如果OR操作,如果任何操作数计算为true,则可以跳过剩余评估

所以通过使用&&或|| 在不评估所有子表达式的情况下,可以将整个表达式计算为true或false。

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

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

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

这也保证了短路。