MonoDevelop建议转向:
if (someBoolVar)
anotherBoolVar = true;
进入这个:
anotherBoolVar |= someBoolVar;
当我将anotherBoolVar
设置为false
时,它也会这样做:
if (someBoolVar)
anotherBoolVar = false;
变为:
anotherBoolVar &= !someBoolVar;
有人可以解释这些陈述是否相同吗?
答案 0 :(得分:12)
嗯,在功能上他们是等同的。
在第一种情况下,如果anotherBoolVar
为true
,您希望将someBoolVar
设置为true
,无论anotherBoolVar
当前具有什么值,替换表达式那样做。
这是短暂的:
anotherBoolVar = anotherBoolVar | someBoolVar;
第二个替换也与它替换的代码相同,并且简称:
anotherBoolVar = anotherBoolVar & (!someBoolVar);
解决方案隐藏在"按位"在这种情况下,布尔变量的性质。使用反转值(~
反转someBoolVar
)和将有效地说"保留!someBoolVar
中设置的所有位并清除rest",意思是如果someBoolVar
为真,则会将其反转为false,并且您将有效地清除anotherBoolVar
。
现在,你应该这样做吗??
在我看来,没有。代码更具可读性。保持,甚至可能寻找一种方法让MonoDevelop在将来不再提出这些建议。
答案 1 :(得分:3)
IDE代码建议通常是双刃剑。是的,这些陈述更为严厉,但它们也可能令人困惑(因此你在思考)。
if (someBoolVar)
anotherBoolVar = someBoolVar;
与
相同anotherBoolVar |= someBoolVar;
因为如果someBoolVar为false,|=
会短路。如果someBoolVar为true,则它不会短路,因此将someBoolVar值(true)分配给anotherBoolVar。
虽然可以略微优化更简洁的陈述,但我建议您坚持使用if语句,因为它更具表现力和可读性。
对于这些类型的if语句,我尝试将它们保持在一行:
if (someBoolVar) anotherBoolVar = someBoolVar;
答案 2 :(得分:2)
例如
if (someBoolVar)
anotherBoolVar = true;
因此当someBoolVar
为true
时,它会归结为
anotherBoolVar = (whatever boolean value of anotherBoolVar) | true;
总是评估为真。
答案 3 :(得分:2)
对于第一次更改,if
构造意味着:
someBoolVar is true ==> anotherBoolVar becomes true
someBoolVar is false ==> anotherBoolVar is unchanged
|=
构造意味着:
someBoolVar is true ==> anotherBoolVar becomes (true | initial value) which is always true
someBoolVar is false ==> anotherBoolVar becomes (false | initial value) which is always equal to the initial value
类似的评论适用于第二次改变,尽管@Lasse V. Karlsen提到,&=
构造似乎缺少一个代号。
答案 4 :(得分:1)
也许布尔代数上的Wikipedia article有帮助。
这个建议是微观优化,可以快速转变宏观。即时编译器为if()语句生成条件分支,至少Microsoft创建的分支不够智能,无法自行优化代码。您必须查看Mono抖动是否可以通过查看生成的机器代码来做得更好。典型的代码生成如下:
if (someBoolVar) anotherBoolVar = true;
00007FFD989F3BB1 movzx eax,cl
00007FFD989F3BB4 test eax,eax
00007FFD989F3BB6 je 00007FFD989F3BBA // <=== here
00007FFD989F3BB8 mov dl,1
00007FFD989F3BBA etc...
上述机器代码中的JE指令等条件分支对于现代处理器来说很麻烦,它在很大程度上依赖于管道来使代码快速执行。指令解码和微操作生成是提前完成的。对预取器来说也是一个非常重要的事情,它试图猜测缓存中需要提供哪些内存位置,这样执行引擎在需要内存内容时不会停止。与处理器执行引擎的原始执行速度相比,内存非常非常慢。
处理器具有分支预测器,它会跟踪先前执行代码时是否执行了分支。并假设分支将再次以相同的方式运行。如果它猜错了那么管道需要刷新。很多工作都被扔掉了,处理器会在填满时停止运转。如果预取者猜错了,那么可能会发生额外的长时间失误。有一个good SO post可以解释错误预测的后果。
使用布尔代数避免分支,它将生成OR或AND指令,它们只需一个循环,并且永远不会刷新管道。当然是微优化,当代码位于确定程序速度的约10%的代码内时,它只会变成宏。 IDE不会很聪明地告诉你是否是这种情况,只有一个分析器可以告诉你。
Fwiw,有更多这样的微优化,程序员倾向于使用&amp;&amp;和和||运营商不恰当。这些操作员的短路行为总是需要机器代码中的分支。这种行为并不总是需要的,通常它不是和&amp;和|运算符可以生成更快的代码。如果左侧操作数预测不佳,那么它可以使代码慢500%。
答案 5 :(得分:0)
if (someBoolVar)
anotherBoolVar = true;
相当于
if (someBoolVar)
anotherBoolVar = true;
else
anotherBoolVar = anotherBoolVar //Nop
相当于
if (someBoolVar)
anotherBoolVar = anotherBoolVar | someBoolVar;
else
anotherBoolVar = anotherBoolVar | someBoolVar //Nop
因为x | true == true和x | false == x
我猜你知道
anotherBoolVar |= someBoolVar
相当于
anotherBoolVar = anotherBoolVar | someBoolVar