【问题标题】:Short circuiting statement evaluation -- is this guaranteed? [C#]短路声明评估——这是有保证的吗? [C#]
【发布时间】:2011-02-11 03:19:48
【问题描述】:

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

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

//....
}

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

【问题讨论】:

  • 如果你问这个问题是因为你确实从上面的代码中得到了一个空引用异常,这可能是因为MyArray 为空或MyArray[0] 包含一个空值。看我的回答。

标签: c# conditional-operator logical-operators short-circuiting


【解决方案1】:

是的,这是有保证的。

C# Language Specification - 7.11 Conditional logical operators:

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

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

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

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

【讨论】:

  • 语言规范在哪里?
【解决方案2】:

是的,这是有保证的。

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

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

【讨论】:

    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

      只是一个小小的观察。

      你是这么说的:

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

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

      仍然如果您的 MyArray 对象中的第一项实际上为空(或者如果其中的任何 其他 对象那个表达式是)。

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

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

      【讨论】:

      • 我想你提到了:if (!conditionHolds)
      • @riffnl:不,我只是让我的示例与 OP 的代码保持一致。 (他/她似乎希望代码在否定情况下做某事。)
      【解决方案5】:

      是的,

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

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

      但也要考虑它的side effectThis article 可能有助于通过一些真实世界的示例深入了解短路评估。

      【讨论】:

        【解决方案6】:

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

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

        这也保证短路。

        【讨论】:

        • 这个代码的结果和他的不一样。在他的情况下,如果计数为0,则短路并进入块。在您的情况下,它在第一个元素的值为 0 时进入块。
        猜你喜欢
        • 2013-10-18
        • 1970-01-01
        • 2011-08-07
        • 2012-02-10
        • 2015-07-04
        • 2021-11-21
        相关资源
        最近更新 更多