C# 将短路运算符与常规运算符组合是否会更改表达式的结果?
我一直认为使用条件布尔运算符(又称短路)代替常规布尔运算符不会影响表达式的结果C# 将短路运算符与常规运算符组合是否会更改表达式的结果?,c#,boolean-logic,short-circuiting,C#,Boolean Logic,Short Circuiting,我一直认为使用条件布尔运算符(又称短路)代替常规布尔运算符不会影响表达式的结果 var result = true | false & false; 结果与 var result = true || false && false 这两个表达式都会导致true 但如果我混合使用正则运算符和条件运算符呢 var result1 = true || false & false; var result2 = true | false && false;
var result = true | false & false;
结果与
var result = true || false && false
这两个表达式都会导致true
但如果我混合使用正则运算符和条件运算符呢
var result1 = true || false & false;
var result2 = true | false && false;
你会期待什么?我希望这些仍然返回true
。但事实并非如此。结果2将为false
我知道这是因为我们的关系。优先顺序是&&&&&&
。这对我来说似乎是违反直觉的。我希望顺序是&&&&| | |
,在这种情况下,所有结果都是相同的(我认为)
所以我想我真正的问题不是短路是否能改变结果。问题是为什么优先顺序是短路可以改变结果
var result2 = true | false && false;
计算如下:
var result2 = (true | false) && false;
因为|
在&&
之前。现在(true | false)
的计算结果为true
,true&&false
为false
至于原因,请参见:
&&和| |运算符后来因其“短路”行为而添加。丹尼斯·里奇(Dennis Ritchie)回顾时承认,当添加逻辑运算符时,按位运算符的优先级应该改变。但由于当时存在数百KB的C源代码,并且安装了三台计算机,丹尼斯认为C语言的变化太大了
&和|运算符计算两个参数(可能涉及调用一个方法),然后返回and-or操作的结果 &&和| |运算符仅对其参数进行求值,直到最终结果完全确定为止 例如:
true | SomeMethod()
和
false&SomeMethod()
调用SomeMethod()函数
true | | SomeMethod()
和
false&&SomeMethod()
不要
true
和false
在本例中也可以是变量当然,我只是简单地使用常量使示例更容易理解。所讨论的运算符的优先级似乎是直接从C(和C++)编程语言中的优先级复制而来的
现在在C语言中,他们对整数和布尔不使用不同的类型。例如,他们可以写:
if (i | j && x > 0) // cf. the result2 of your question
这应该意味着“整数i
和j
按位or'ed给出非零的值,而数字x
为正”。因此,当操作数被认为是整数(许多位数)时,应该主要使用|
和&
,当操作数被认为是布尔数时,应该主要使用|
和&
因此,在C语言中,
绑定比&
更严格似乎是很自然的
在C#中,我们具有更高的类型安全性,并且没有从Int32
到Boolean
或从Boolean
到Int32
的转换。因此,不再可能“混合”事物,优先顺序也不再感觉自然
我想在理论上,在C#中,可以使运算符
public static bool operator |(bool b, bool c)
public static int operator |(int i, int j)
具有与运算符不同的优先级
public static bool operator |(bool b, bool c)
public static int operator |(int i, int j)
但这真的不会让事情变得更好吗
我认为很少有人在同一个表达式中使用布尔非短路运算符,如
|
和短路运算符,如&&
,但当他们这样做时,他们应该非常小心优先级,或者只是在那里加上括号()
(这也会使意图更加清楚).短路肯定会改变副作用(即,如果布尔表达式是方法),因此进行区分是有意义的。@Antonijn:你的意思是它会改变副作用吗?对不起,我应该更清楚。答案很无聊,这是因为它继承了C语言的优先级和关联性规则,就像所有花括号语言一样。通过扮演语言设计师的角色使其有趣,并提出替代方案。您只有几个选择,优先级可以是相反的或相等的。如果等于,则结合性很重要,这可能是您忽略的。据我所知,&和|运算符用于按位运算,它们不是您在第一句“常规布尔运算符”中所能做到的。因为bool可以表示单个位,所以它也适用于它们。“& &和”算子是真值的逻辑运算符。毫无疑问,C++的设计者只是简单地复制了C和C++中已知的优先级。但请注意,您所指的线程主张将操作符&
和|
从&&
和|
移动到==
和的更远处=
运算符,使&
和|
先出现,然后出现==
和=编码>,然后才是&
和|
。这在C语言中就不那么容易混淆了,因为它们对整数和布尔值使用相同的类型。因此,当他们说if(i&j==0)
时,它可以很好地编译(不会用C#withint
编译),但肯定不同于预期的if((i&j)==0)
。我认为只有在需要按位和/或时才使用&
和
。从现在起,对于布尔和/或,我将始终使用&&
和|
。