在 if 语句中对同一个表达式求值两次有什么好处?
Any benefit to evaluating the same expression twice in an if-statement?
我正在对外国(即不是我的)C# 代码进行一些维护,我遇到了这种情况:
class AClass : System.Windows.Forms.Form {
bool aMemberField = false;
void someMemberFunction() {
if ((aMemberField || aMemberField)) return;
// function continues
}
// more members ...
}
在 C# 中执行此操作是否有任何 benefit/effect,或者它只是浪费评估?如果它有任何价值,这部分项目是 Windows 形式 class,由 class 继承表示。
提前致谢。
编辑:
你的回答证实了我的猜测,谢谢。我查看了项目以查找成员字段在其他表达式中使用的位置,并且在几乎所有与另一个成员一起评估的表达式中,它都是相同的 other 成员,即
if((aMemberField || bMemberField))
所以我倾向于认为这只是程序员的错字,复制粘贴将其传播到程序中的另一个实例。
这样做是没有意义的。我想不出在什么情况下它总是 return aMemberField
的值,因为 true || true = true
和 false || false = false
.
有一种模式需要对一个表达式求值两次,但它与多线程访问有关。您检查资源是否可用,如果可用,则将其锁定(防止进一步修改),然后检查资源是否再次可用,因为它可能在您锁定之前已被修改。
您提供的代码是多余的。即使在多线程场景下,如果第一个求值是true,那么第二个就不是运行,如果第一个是false,第二个是true,那是一个很随机的事件。另外,编译器可能会优化它的 s**t,无论如何它都不会像上面描述的那样工作。
你的线路
if ((aMemberField || aMemberField))
是短路评价。如果变量为真,则只会评估一个变量,它会进入条件语句下方的代码块。如果变量为假,它将 运行 无用且多余的二次评估。
无论如何,这是 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
没用。即使有一些非常奇怪的边缘情况(参见菱铁矿的回答),它也只是证明代码需要一些认真的重构。
我正在对外国(即不是我的)C# 代码进行一些维护,我遇到了这种情况:
class AClass : System.Windows.Forms.Form {
bool aMemberField = false;
void someMemberFunction() {
if ((aMemberField || aMemberField)) return;
// function continues
}
// more members ...
}
在 C# 中执行此操作是否有任何 benefit/effect,或者它只是浪费评估?如果它有任何价值,这部分项目是 Windows 形式 class,由 class 继承表示。
提前致谢。
编辑:
你的回答证实了我的猜测,谢谢。我查看了项目以查找成员字段在其他表达式中使用的位置,并且在几乎所有与另一个成员一起评估的表达式中,它都是相同的 other 成员,即
if((aMemberField || bMemberField))
所以我倾向于认为这只是程序员的错字,复制粘贴将其传播到程序中的另一个实例。
这样做是没有意义的。我想不出在什么情况下它总是 return aMemberField
的值,因为 true || true = true
和 false || false = false
.
有一种模式需要对一个表达式求值两次,但它与多线程访问有关。您检查资源是否可用,如果可用,则将其锁定(防止进一步修改),然后检查资源是否再次可用,因为它可能在您锁定之前已被修改。
您提供的代码是多余的。即使在多线程场景下,如果第一个求值是true,那么第二个就不是运行,如果第一个是false,第二个是true,那是一个很随机的事件。另外,编译器可能会优化它的 s**t,无论如何它都不会像上面描述的那样工作。
你的线路
if ((aMemberField || aMemberField))
是短路评价。如果变量为真,则只会评估一个变量,它会进入条件语句下方的代码块。如果变量为假,它将 运行 无用且多余的二次评估。
无论如何,这是 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
没用。即使有一些非常奇怪的边缘情况(参见菱铁矿的回答),它也只是证明代码需要一些认真的重构。