17

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

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

//....
}

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

4

6 回答 6

36

是的,这是有保证的。

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

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

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

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

  • 只有条件运算符支持短路,逻辑运算符不支持。
  • C# 的逻辑运算符看起来就像它们的条件对应物,但少了一个字符,所以逻辑 OR 是|,逻辑 AND 是&
  • 逻辑运算符可以重载,但条件运算符不能(这有点技术性,因为条件运算符评估确实涉及重载决策,并且此重载决策可以解析为类型的逻辑运算符的自定义重载,因此您可以解决此限制到一定程度上)。
于 2010-04-22T15:28:13.630 回答
12

是的,这是有保证的。

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

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

于 2010-04-22T15:28:24.237 回答
5

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

于 2010-04-22T15:31:48.387 回答
2

只是一个小小的观察。

你这样说:

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

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

如果您的对象中的第一项实际上是 null (或者如果该表达式中的任何其他对象是),您仍然有可能获得 a 。NullReferenceExceptionMyArray

唯一完全安全的检查是:

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

if (conditionHolds)
{
    //....
}
于 2010-04-22T16:19:04.820 回答
2

是的,

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

所以通过使用 && 或 || 运算符,整个表达式可以被评估为真或假,而无需评估所有子表达式。

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

于 2016-05-01T06:59:57.983 回答
-1

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

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

//.... 
} 

这也保证短路。

于 2010-04-22T15:36:03.350 回答