C#中逻辑AND、条件AND和OR有什么区别?

61

可能是重复问题:
什么是 | 和 || 或运算符之间的区别?

逻辑 AND 和 OR:

(x & y)
(x | y)

条件与和条件或:

(x && y)
(x || y)

到目前为止,我只知道条件运算符。我知道它的作用并且知道如何在if语句中应用它。但是逻辑运算符有什么作用呢?

3个回答

86

我更喜欢将其称为“按位与条件”而不是“逻辑与条件”,因为“逻辑”的一般概念在两种情况下都适用。

x & y    // bitwise AND, 0101 & 0011 = 0001
x | y    // bitwise OR,  0101 | 0011 = 0111

x && y   // true if both x and y are true
x || y   // true if either x or y are true

编辑

根据广大需求,我还应该提到参数的求值方式不同。在条件表达式中,如果整个操作的结果可以由第一个参数决定,第二个参数将不会被求值。这被称为短路求值。位运算必须计算两侧才能得出最终值。

例如:

x.foo() && y.bar()

只有当x.foo()评估为true时,才会调用y.bar()。反之亦然,

x.foo() || y.bar()

只有当x.foo()计算结果为false时,才会调用y.bar()


1
@John Weldon:这个问题是关于操作符之间的区别,而懒惰肯定是其中之一。 - Dirk Vollmar
1
请注意 - 逻辑运算符和条件运算符是微软对它们的命名定义。详情请参考:http://msdn.microsoft.com/en-us/library/6a71f45d%28v=vs.80%29.aspx - Mad Halfling
@Henk:看一下我正在回答的问题... 数据类型没有被指定。这是一个概念性的回答,而不是一个吹毛求疵的细节问题。 - Cogwheel
1
当这个答案在另一个问题下被用来“证明”&是按位布尔运算符时,我来到了这里。没有通用的答案,你的开头句子完全是错误的。 - H H
@Henk:所以你投票反对这个答案,因为它不适用于一个它本来就不应该回答的问题??我建议你重新阅读一下这个答案实际适用的问题。我的第一句话并没有错,它是在澄清原始问题中的一个误解。 - Cogwheel
显示剩余9条评论

35
(x && y) 

Python中的逻辑运算符`and`是懒惰求值的。只有在`x`为真时,才会对`y`进行求值。

(x & y)

不是惰性的。 y将始终被评估。


17
那只是故事的一半,而且可以说是较不重要的那一半。 - Kennet Belenky
3
@John,完全正确。在处理布尔值时,唯一的区别是“惰性”。实际上,无论是处理布尔值还是较大的整型,操作都没有任何不同。它在两个单一比特位上执行位运算,并返回一个比特位。 - spender
3
@John,这是事实。根据C#规范第7.10.3节的布尔逻辑运算符: "如果x或y为真,则x | y的结果为true。否则,结果为false。" 同样请参阅第7.11节条件逻辑运算符:"操作x || y对应于操作x | y,只是当x为false时才评估y。" - Michael Stum
3
@Robert,我承认在布尔值方面的参考。你肯定同意这个问题比那更广泛吧? - John Weldon
5
呃,我想我会去回答一些其他的问题。 - Robert Harvey
显示剩余15条评论

11

更新的答案 - 我原来的回答有误导和不完整之处。

首先,我应该为我对这个问题的评论和回复道歉。

在阅读规范后,按位运算符和条件运算符之间的区别变得不那么明显了。

根据ECMA-334的第14.10节

&、^和|运算符被称为逻辑运算符。

对于整数运算:

1. &运算符计算两个操作数的按位逻辑与,|运算符计算两个操作数的按位逻辑或,^运算符计算两个操作数的按位逻辑异或。2. 这些运算不可能发生溢出。

根据第14.11节

&&和||运算符被称为条件逻辑运算符。2. 它们也被称为“短路”逻辑运算符。

14.11.1

1. 当&&或||的操作数是bool类型,或者操作数是未定义适用的&或|运算符但定义了对bool的隐式转换的类型时,操作将按以下方式处理:2. 操作x&&y计算为x?y:false。3. 换句话说,首先评估并转换x为bool类型。4. 然后,如果x为true,则评估并转换y为bool类型,并将其作为操作的结果。5. 否则,操作的结果为false。6. 操作x || y计算为x?true:y。7. 换句话说,首先评估并转换x为bool类型。8. 然后,如果x为true,则操作的结果为true。9. 否则,评估并转换y为bool类型,并将其作为操作的结果。

14.11.2

当操作数为声明可应用的用户定义操作符&或者|的类型时,并且选择的运算符所在的类型为T,则必须满足以下两个条件:
1. 选择的运算符的返回类型和每个参数的类型都必须为T。 2. 换句话说,该运算符必须计算类型T的两个操作数的逻辑AND或逻辑OR,并且必须返回T类型的结果。 3. T必须包含operator true和operator false的声明。
如果不满足这些要求,则会出现编译时错误。否则,&&或||操作将通过将用户定义的true或false运算符与所选的用户定义运算符结合起来进行评估。
x && y的操作按以下方式进行评估:T.false(x)?x:T.&(x,y),其中T.false(x)是在T中声明的false运算符的调用,T.&(x,y)是所选运算符&的调用。换句话说,首先对x进行评估并对结果调用false运算符以确定x是否明确为false。然后,如果x明确为false,则操作的结果为之前为x计算的值。否则,y被评估,并在先前为x计算的值和为y计算的值上调用所选的运算符&以生成操作的结果。
x || y的操作按以下方式进行评估:T.true(x)?x:T.|(x,y),其中T.true(x)是在T中声明的true运算符的调用,T.|(x,y)是所选运算符|的调用。换句话说,首先对x进行评估并对结果调用true运算符以确定x是否明确为true。然后,如果x明确为true,则操作的结果为之前为x计算的值。否则,y被评估,并在先前为x计算的值和为y计算的值上调用所选的运算符|以生成操作的结果。
无论哪种操作,给定的x表达式仅被评估一次,而给定的y表达式要么不被评估,要么被评估一次。
有关实现operator true和operator false的类型示例,请参见§18.4.2。

4
&|^ 是重载运算符。对于两个布尔值,它们只是急切的(非条件)逻辑运算符(ECMA-364 §14.10.3)。 - Matthew Flaschen
@Matthew,这个问题的范围比布尔值更广泛。 - John Weldon
实际上我认为我不同意。从第二个示例看得出x和y是布尔值。按位运算符从未涉及到这个问题。 - Matthew Flaschen
@Matthew;同意,可以这样解释。 - John Weldon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接