在if语句中两次评估同一个表达式有什么好处?

时间:2016-03-10 08:42:03

标签: c# if-statement boolean-expression

我正在对外国(即非我的)C#代码进行一些维护,我遇到了相应的情况:

class AClass : System.Windows.Forms.Form {
    bool aMemberField = false;

    void someMemberFunction() {
        if ((aMemberField || aMemberField)) return;
        // function continues
    }

    // more members ...
}

在C#中执行此操作是否有任何好处/效果,还是仅仅浪费评估?如果它有任何价值,项目的这一部分是一个Windows Form类,由类继承表示。

提前致谢。

修改

您的回答证实了我已经怀疑的内容,谢谢。我查看了项目以找到成员字段在其他表达式中使用的位置,并且在几乎所有与其他成员一起评估的表达式中,它都是相同的其他成员,即

if((aMemberField || bMemberField))

所以我倾向于认为这只是程序员的错误,而复制粘贴已经将它传播到程序中的另一个实例。

3 个答案:

答案 0 :(得分:2)

有一种模式需要两次评估表达式,但它与多线程访问有关。您检查资源是否可用,如果是,则将其锁定(防止进一步修改),然后检查资源是否再次可用,因为它可能在您锁定之前就已被修改。

您在那里展示的代码只是多余的。即使在多线程场景中,如果第一次评估为真,那么第二次评估不会运行,如果第一次评估为假而第二次评估为真,那么这是一个非常随机的事件。此外,编译器可能会对其进行优化,但无论如何都不会如上所述。

答案 1 :(得分:1)

你的行

if ((aMemberField || aMemberField))

是一种短路评估。如果变量为true,则只评估一个变量,并且它将在条件语句下面输入代码块。如果变量为假,则会进行无用且冗余的二次评估。

无论如何,这里是IL

if(aMemberField || aMemberField)

IL_0000:  nop         
IL_0001:  ldc.i4.0    
IL_0002:  stloc.0     // aMemberField
IL_0003:  ldloc.0     // aMemberField
IL_0004:  ldloc.0     // aMemberField
IL_0005:  or          
IL_0006:  stloc.1     
IL_0007:  ldloc.1     
IL_0008:  brfalse.s   IL_000C
IL_000A:  br.s        IL_000C
IL_000C:  ret         

if(aMemberField)

IL_0000:  nop         
IL_0001:  ldc.i4.0    
IL_0002:  stloc.0     // aMemberField
IL_0003:  ldloc.0     // aMemberField
IL_0004:  stloc.1     
IL_0005:  ldloc.1     
IL_0006:  brfalse.s   IL_000A
IL_0008:  br.s        IL_000A
IL_000A:  ret  

它毫无用处。即使有一些非常奇怪的边缘情况(参见Siderite的回答),它只是证明代码需要一些严肃的重构。

答案 2 :(得分:0)

做这样的事是没有意义的。我无法想到这样一种情况,因为它始终会返回aMemberFieldtrue || true = true之后false || false = false的值。