【问题标题】:Does combining short-circuiting operators with regular operators change the result of the expression?将短路运算符与常规运算符结合使用会改变表达式的结果吗?
【发布时间】:2013-01-18 06:43:14
【问题描述】:

我一直认为使用条件布尔运算符(也称为短路)代替常规布尔运算符不会影响表达式的结果。

var result = true | false & false;

结果与

相同
var result = true || false && false

两个表达式的结果都是true

但是,如果我将常规运算符和条件运算符混合使用会怎样?

var result1 = true || false & false;
var result2 = true | false && false;

你会期待什么?我希望这些仍然会返回true。但事实并非如此。结果 2 将是 false!

我知道这是因为operator precedence。优先顺序为& | && ||。这对我来说似乎违反直觉。我希望订单为& && | ||,在这种情况下,所有结果都是相同的(我认为)。

所以我想我真正的问题不是 如果 短路可以改变结果。问题是为什么优先顺序是这样的,短路可以改变结果。

【问题讨论】:

  • 短路肯定会改变副作用(即如果布尔表达式是方法),因此进行区分是有意义的。
  • @Antonijn:你的意思是它可以改变副作用吗?
  • 对不起,我应该更清楚的。
  • 答案很无聊,因为它继承了 C 的优先级和关联性规则,就像所有花括号语言一样。通过扮演语言设计者的角色来让它变得有趣,并提出一个替代方案。您只有几个选择,优先级可以相反或相等。如果相等,则关联性很重要,可能是您忽略的。

标签: c# boolean-logic short-circuiting


【解决方案1】:

相关运算符的优先级似乎直接从 C(和 C++)编程语言中的优先级复制而来。

现在在 C 中,它们不会对整数和布尔值使用不同的类型。例如,他们可以写:

if (i | j && x > 0)      // cf. the result2 of your question

这应该意味着“整数ij 按位或'ed 给出非零并且数字x 是正数”。所以|& 应该主要在操作数被认为是整数(多位数)时使用,而||&& 应该主要在操作数被认为是时使用布尔值。

所以在 C 中| 的绑定比&& 更严格似乎很自然。

在 C# 中,我们具有更高程度的类型安全性,并且没有从 Int32Boolean 或从 BooleanInt32 的转换。因此,不再可能“混合”事物,优先级也不再自然。

我猜理论上在 C# 中,可以制作运算符

public static bool operator |(bool b, bool c)

与运算符有一个不同的优先级

public static int operator |(int i, int j)

但它真的不会让事情变得更好吗?

我认为人们在同一个表达式中使用 boolean 非短路运算符如| 和短路运算符如&& 是非常罕见的,但当他们这样做时,他们应该要么对优先级非常小心,要么把括号 () 放在那里(这也会使意图更清楚)。

【讨论】:

    【解决方案2】:

    &和|运算符评估两个参数(可能涉及调用方法),然后返回与或或操作的结果。

    && 和 ||运算符只评估他们的参数,直到最终结果完全确定。

    例如: true | SomeMethod()false & SomeMethod() 调用 SomeMethod() 函数 true || SomeMethod()false && SomeMethod()不要。

    这个例子中的truefalse当然也可以是变量,我只是简单地使用了常量,让例子更容易理解。

    【讨论】:

      【解决方案3】:
      var result2 = true | false && false;
      

      计算为:

      var result2 = (true | false) && false;
      

      因为|&& 之前。现在(true | false) 计算结果为true,而true && false 为假。

      至于为什么,见this question

      && 和 ||后来添加了运算符,因为它们的“短路”行为。 Dennis Ritchie 回想起来承认,当添加逻辑运算符时,应该更改按位运算符的优先级。但由于当时存在数百 KB 的 C 源代码和三台计算机的安装基础,Dennis 认为 C 语言的变化太大了......

      【讨论】:

      • 据我所知 & 和 |运算符用于按位运算,它们不是您在第一句“常规布尔运算符”中可以使用的。由于 bool 可以表示单个位,因此它也适用于它们。 && 和 ||运算符是真值的逻辑运算符。
      • 毫无疑问,C# 的设计者只是简单地复制了 C 和 C++ 中已知的优先级。但请注意,您所指的线程主张将运算符 &| 进一步 远离 &&||,“通过”== 和 @ 987654334@ 运算符,因此 &| 先出现,然后是 ==!=,然后才出现 &&||。这在 C 中不会那么混乱,因为它们对整数和布尔值使用相同的类型。因此,当他们说 if (i & j == 0) 时,它编译得很好(不会在 C# 中用 int 编译),但肯定与预期的 if ((i & j) == 0) 不同。
      • 我认为只在需要按位和/或时使用&| 是个好主意。从现在开始,对于布尔值和/或我将始终使用 &&||
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-10-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多