我只是注意到按位操作不是" smart"作为逻辑"和\或"操作,我想知道为什么?
以下是一个例子:
// For the record
private bool getTrue(){return true;}
private bool getFalse(){return false;}
// Since a is true it wont enter getFalse.
bool a = getTrue() || getFalse();
// Since a is false it wont enter getTrue.
bool b = getFalse() && getTrue();
// Since b is false it wont enter getTrue.
b = b && getTrue();
然而,按位运算符" | ="和"& ="并不聪明:
bool a = getTrue();
a |= getFalse(); // a has no chance to get false but it still enters the function.
a = getFalse();
a &= getTrue(); // a has no chance to get true but still performs this operation.
我想知道为什么他们不能以同样的逻辑方式工作。
答案 0 :(得分:10)
一个澄清:
在&=
上进行求值时,运算符|=
和bool
不是按位运算符 - 它们是逻辑运算符,但它们相当于x = x & y
和{{1 }},它不像x = x | y
和&&
那样短路。
来自MSDN:
&运算符对积分操作数和bool操作数上的逻辑AND执行按位逻辑AND运算。
设计师可以实施||
和||=
,但由于仅适用于布尔类型,因此那里没什么价值。
答案 1 :(得分:8)
D Stanley's answer是正确的;您的错误是在&
应用于bool
时将其视为“按位”。在应用于&
时,最好将&&
和bool
视为逻辑AND的渴望和懒惰版本。
现在这是一个你没有问的问题,但实际上是一个更有趣的问题:
为什么首先存在
bool
的AND和OR的非短路版本?也就是说,为什么你会说exprX & exprY
而不是exprX && exprY
?
错误的原因是:无论exprY
的值如何,表达式exprX
都可能会产生副作用。这是一个不好的理由,因为将表达式用于其副作用及其值是一个值得怀疑的做法。
很好的理由是:计算&
比&&
更快。
怎么可能?当然,如果我们可以在某些时候避免计算右侧,那么我们可以始终平均节省时间,对吗?
错误的错误。 z = x && y
将生成为具有以下结构的代码:
if x goto CONSEQUENCE
z = false
goto DONE
CONSEQUENCE: z = y
DONE:
与简单地计算x & y
并将结果分配给z
相比,这是很多指令,大型代码需要更多时间来加载磁盘,更多时间进行jit编译,并占用更多空间在处理器缓存中。
此外,这些指令包含条件分支和非条件分支,大大增加了抖动必须处理的基本块的数量。 (“基本块”是一段具有明确开始和结束的代码,如果没有异常,基本块中的所有代码都会执行。)当基本块的数量时,抖动可能会选择避开某些优化必须分析得太大。
最糟糕的是,任何条件分支都会让CPU有机会让其分支预测器做出错误的选择,这在某些情况下可能会产生严重的性能影响。
现在,这并不是说你永远不应该使用&&
作为bools;目前还没有程序在市场上取得的巨大成功归功于这种纳米优化的使用。我只是因为并不完全明白为什么在bool上应该有一个非短路的逻辑运算符,这一点。
答案 2 :(得分:2)