C# 为什么不';t位运算符与逻辑运算符一样智能”;和/或;操作员

C# 为什么不';t位运算符与逻辑运算符一样智能”;和/或;操作员,c#,optimization,operators,bit-manipulation,C#,Optimization,Operators,Bit Manipulation,我刚刚注意到按位操作不像逻辑的“和/或”操作那么“聪明”,我想知道为什么 下面是一个例子: // 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 en

我刚刚注意到按位操作不像逻辑的“和/或”操作那么“聪明”,我想知道为什么

下面是一个例子:

// 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.

我想知道为什么它们不以同样的逻辑方式工作。

主要区别在于您使用的是/还是/。后者短路(您称之为“智能”),而前者则不短路(这是处理布尔类型时运算符之间的唯一区别)。由于没有
&&=
|124;=
运算符,因此您只注意到
&=
|=
,正如符号所示,它们不会短路

我认为很可能存在
&=
|=
&&=
|=
并不是因为前者使用的是数字类型,短路没有意义。

一个澄清:

当在
bool
s上求值时,运算符
&=
=
不是位运算符-它们是逻辑运算符,但它们等效于
x=x&y
x=x | y
,它们不像
&
那样短路

发件人:

运算符对整数操作数和布尔操作数执行逐位逻辑“与”运算

设计者本可以实现
|124;=
&&=
,但由于它们只适用于布尔类型,因此没有多少价值

是正确的;当应用于
bool
时,您的错误是认为
&
是“按位”的。最好将
&
&
视为应用于
bool
时逻辑and的渴望和懒惰版本

这是一个你没有问的问题,但实际上是一个更有趣的问题:

首先,为什么有非短路版本的AND AND OR for
bool
?也就是说,为什么你会说
exprX&exprY
而不是
exprX&exprY

不好的原因是:expression
exprY
可能会产生一种副作用,不管
exprX
的值是多少,您都希望这种副作用总是发生。这是一个不好的理由,因为使用表达式的副作用和价值都是一个值得怀疑的做法

好的理由是:计算
&
&
更快

这怎么可能?当然,如果我们可以避免计算右手边的一些时间,那么我们总是可以平均节省时间,对吗

错了
z=x&&y
将作为具有以下结构的代码生成:

if x goto CONSEQUENCE
z = false
goto DONE
CONSEQUENCE: z = y
DONE: 
与简单地计算
x&y
并将结果分配给
z
相比,这是很多指令,而大型代码需要更多的时间从磁盘加载,更多的时间进行jit编译,并占用处理器缓存中更多的空间

此外,这些指令包含一个条件分支和一个非条件分支,大大增加了抖动必须处理的基本块的数量。(一个“基本块”是一段有明确开始和结束的代码,如果没有异常,基本块中的所有代码都会执行。)当需要分析的基本块数量过大时,抖动可能会选择避免某些优化

最糟糕的是,任何条件分支都会给CPU一个机会,使其分支预测器做出错误的选择,这在某些情况下会对性能产生严重影响


现在,这并不是说你不应该对bools使用
&&
;目前还没有一个项目在市场上的巨大成功归功于这种纳米优化的使用。我指出这一点仅仅是因为根本不清楚为什么布尔运算中应该有一个非短路逻辑运算符。

非常有趣,这是我过去一直想知道的!虽然现在我很好奇为什么这个功能会被列入“已实现”列表,而不是被列在“很好拥有”下。@BenAaronson:首先,它是一个非常简单的功能;如果您已经有了任何二进制运算符,那么再添加一个并不困难。其次,在这样一个世界中,任意类都可以有用户定义的
&
运算符,但
bool
却没有,你会说吗?@EricLippert谢谢你的肯定-现在,如果你能证实我的猜测,实施
&&
|124;=
的价值不值得我为一个快乐的人退休而付出的代价。:)@德斯坦利:奇怪的是,当我在愚人节写了一篇关于疯狂复合运算符的帖子时,我甚至没有想到要包括
&&
|124;=
。这就是他们离我有多远。:-)在C#中,像
2&true
这样的操作会发生什么?也就是说,您正在计算的
&
同时具有int和bool操作数
&
是为两个int操作数或两个bool操作数定义的,但不是每个操作数中的一个,因此其中一个操作数需要转换为bool或int,以便它们匹配,对吗?所以,我的问题是:
2&true
会在C中变成
int&int
aka
2&1
aka
0
(如果转换为bool,则为false)还是a
bool&bool
aka
true
?@Apriori
2&true
不会编译。在C#中,您不能将
bool
转换为
int
,反之亦然。