【问题标题】:Is there a reason to use &= rather than just = on a boolean?是否有理由在布尔值上使用 &= 而不仅仅是 = ?
【发布时间】:2013-10-09 15:09:34
【问题描述】:

我今天遇到了一些检查许多错误条件的代码。一直使用单个布尔值,但不是每次都使用= 重新分配它,而是使用&= 重新分配它,从而对布尔值的先前值和新值进行位明智的与运算。代码看起来像这样:

bool result = FirstCheck();
Assert(result);
result &= SecondCheck();
Assert(result);
...

现在我很好奇为什么有人会这样做?这在逻辑上等同于重新分配布尔值,如下面的可能分支所示:

  1. FirstCheck 失败(返回 false)并且程序在 assert 上失败并且永远不会进入 SecondCheck
  2. FirstCheck 通过(返回真),程序进入 SecondCheck。如果 SecondCheck 返回 true,则结果为 true,因为 true&true = true。如果 SecondCheck 返回 false,则结果为 false,因为 true&false = false。

既然没有逻辑上的区别,还有其他原因&= 可能更可取吗?还是更有可能是一些从未更改过的旧代码的遗留物?

编辑: 澄清一下,断言始终是活动代码。实际上,我在调查错误时偶然发现了这段代码,因为断言失败了。

【问题讨论】:

    标签: c# boolean-logic


    【解决方案1】:

    是的,原因是你使用一个布尔值来累积多个函数的返回码。

    如果没有 &=,你会在每次调用时用最新的函数覆盖返回码,因此你只能测试最后一个函数是否成功。使用 &= 如果单个函数返回 false,则从该点开始返回代码保持为 false,因此您知道至少有一个函数失败。

    这样省了写代码

    bFirstCheck == fn1();
    bSecondCheck == fn2();
    bThirdCheck == fn3();
    
    if (bFirstCheck && bSecondCheck && bThirdCheck) {
    }
    

    当您可以编写如下代码时:

    bCheck = fn1();
    bCheck &= fn2();
    bCheck &= fn3();
    
    if (true == bCheck) {
    }
    

    【讨论】:

    • 没有理由将布尔值与true 进行比较。这是一个noop。只需写if(bCheck)
    • 感谢您的出色回应,但是,这并不能真正回答我的具体问题,因为作业之间的断言否定了您在示例中提到的任何好处
    • Assert() 仅适用于调试版本,此处用于提醒您哪个函数失败,它将在发布版本中编译为 NO-OP。
    【解决方案2】:

    我猜一开始是这样的:

    bool result = FirstCheck();
    result &= SecondCheck();
    Assert(result);
    

    所以代码正在检查两个结果是否都是肯定的,但是有人在 firstCheck() 之后添加了 Assert()。

    或者该人可能具有 C++ 背景,并认为位运算符比逻辑运算符快。

    【讨论】:

    • 是否存在位运算符比逻辑运算符快的情况?
    • 这个执行按位与。 & 运算符,当在 C# 中对布尔值调用时,只执行非短路 AND。所以它永远不会更快,它可能会更慢。仅当无论result 的值如何都必须执行SecondCheck 的副作用很重要时才应该这样做。要么这样,要么只是一个错误。
    【解决方案3】:

    您假设断言已启用。如果这是使用Debug.Assert,则只有在定义了DEBUG 条件编译符号时才会实际调用该方法。

    假设稍后使用result(在断言之外),那么FirstCheck() 返回false 时会有所不同。

    【讨论】:

      【解决方案4】:

      正如其他人所说,Assert 可能并不总是活动代码。然后让我们假设第一次和第三次检查返回 true,第二次检查返回 false。因此,如果你有

      x = FirstCheck()
      x = SecondCheck()
      x = ThirdCheck()
      

      那么 x 将等于 true。

      但是,如果你这样做了

      x &= FirstCheck()
      x &= SecondCheck()
      x &= ThirdCheck()
      

      x 等于 false

      【讨论】:

        猜你喜欢
        • 2014-03-04
        • 2017-08-29
        • 1970-01-01
        • 2021-07-11
        • 2017-02-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多