【问题标题】:Why would one use the |= operator on a boolean value in C#?为什么要在 C# 中对布尔值使用 |= 运算符?
【发布时间】:2012-04-12 04:26:00
【问题描述】:

例子:

我们发现这是一些供应商编写的代码,我们正试图弄清楚他们为什么要这样做。

bool tmp = false;

if (somecase)
   tmp = true;

if (someOtherCase)
   tmp |= true;   

【问题讨论】:

  • 右边真的是常数true吗?在布尔值上使用|= 是完全合理的,而很少使用|= true
  • 您知道,即使msdn 在其示例中列出了一个布尔值和|= 运算符...

标签: c# boolean


【解决方案1】:

完全没有理由。布尔值 |= true 将始终为 true。这是一个想花哨的人,或者忘记布尔逻辑=)

将其更改为tmp = true;

【讨论】:

  • 感谢您在经过几个测试程序后我得出了这个结论。这就是我问的原因.. 不安全。
  • @code4life: false | true 仍然是 true... 你是不是也忘记了你的布尔逻辑?
  • @code4life:好吧,如果是这样呢?那么它在“tmp |= true;”之后的状态是什么?
  • tmp |= someOtherCase;会更有意义。也许它是这样开始的,然后不小心被转换成带有 if 的更复杂的形式。
  • |= false 也无用:这是一个空操作。
【解决方案2】:

也许其中一个布尔文字曾经是一个变量,他们只是在更改操作数时没有考虑更改运算符。显然逻辑是等价的。

更有可能的是,他们认为在第二种情况下,他们希望保留评估第一个“if”条件的结果。当然,这是错误的推理。

一个更简单的等效语句:

bool tmp = somecase | someOtherCase;

编辑

正如 pickypg 所指出的,这种说法可能会令人困惑,因为大多数人并不期望 | 具有布尔值,而且许多人不会注意到它,或者不会考虑副作用的含义。最好的表达方式(如果确实有副作用)是 minitech 的解决方案:只需将 |= 更改为 =

或者,如果 someOtherCase 表达式没有副作用,请使用 Jakub Konecki 的解决方案:someCase || someOtherCase

【讨论】:

  • 这就是我们的想法……或者可能是幸运的类型。
  • 我怀疑那是原始代码,但即使这样也应该转换为 bool tmp = somecase || someOtherCase; 以让短路完成它的工作。如果您想要副作用,那么您很可能会通过单行代码来破坏可读性,特别是通过隐式关联在那时只能松散关联的两种方法(因为第一种方法不会通过“失败”来阻止第二种方法) " 或 false 代表的任何内容)。
  • @pickypg 我同意在代码中加上| 会降低可读性。还有很大的可能有人会在某个时候将|“纠正”为||。这两者都是正确的,因为使用带有布尔值的| 并不是真正地道的 C#。我觉得这很可惜,但没有什么可做的。
【解决方案3】:

有趣 - 看起来它正在做同样的事情:

tmp = tmp | true;

这将始终将 tmp 设置为 true。

【讨论】:

    【解决方案4】:

    foo |= truefoo = foo | true 的缩写。

    实际代码可以改写为

    bool tmp = false;
    tmp |= someCase;
    tmp |= someOtherCase;
    

    甚至更好

    someCase || someOtherCase
    

    【讨论】:

    • 小问题:如果 someOtherCase 有副作用,someCase | someOtherCase 会保留它们,而someCase || someOtherCase 不会。
    【解决方案5】:

    与其他 op= 运算符一样,x |= yx = x | y 等效(除了多重评估的副作用)。这是if (!x) x = y;if (y) x = true; 的简洁写法。

    但是,在右侧有一个 常量 没有任何意义。

    • x |= true 更直接地写成x = true
    • x |= false 保持 x 不变。

    他们为什么要这样做。

    一些可能的解释是:

    • 这是一个错字:他们本来打算写 tmp = true; 而不是 tmp |= true;,但从未注意到,因为他们的程序恰好按预期运行。
    • RHS 原本是一个变量,被替换为常量true,没有另外更改代码。
    • tmp 最初是 bitfield|= 更有意义),后来被简化为一个位。

    【讨论】:

      【解决方案6】:

      最终的结果将是“如果任何一种情况为真,则结果为真”。不过,您没有理由必须使用运算符,因为 if 中的 || 也可以正常工作。

      【讨论】:

      • 如果someOtherCase 有副作用,您需要使用| 而不是|| 来保留它们。
      【解决方案7】:

      一个聪明的编译器可以避免这种情况下的赋值,尽管它可能不会因为它不应该短路按位操作。无论如何,这似乎是一种微优化。实际上,我怀疑这是作者使用位标志的一种保留模式(或者他/她只是不明白它是如何工作的)。最好是:

      bool tmp = somecase || someOthercase;
      

      (如果只使用一次,则内联临时)

      请注意,使用标志时,它确实有意义。

      #define CONDITION_ONE 0x01
      #define CONDITION_TWO 0x02
      
      int temp = 0;
      if (somecase) {
         temp = CONDITION_ONE;
      }
      
      if (someOthercase) {
         temp |= CONDITION_TWO;
      }
      

      【讨论】:

      • 这不会保留someOtherCase 的副作用,如果有任何要保留的话。
      • @phoog - 这是真的。如果 case 是函数或包含语句,那么使用惰性求值就不一样了,它们不应该合并。
      • 您可以将它们与| 运算符结合使用。
      • @phoog 那将是最纯粹的邪恶。 IMO,根据读者区分按位或和逻辑或来确定语句的评估(在布尔值上)是最糟糕的编码魔法。我宁愿将条件拆分并在两个语句中进行评估,以明确期望是什么。我一直使用的规则是你只对布尔变量使用逻辑运算符。
      • 我同意你的看法;两个运算符之间的细微差别使得很容易误读一个。但是,您的术语与 Microsoft 的不一致;他们将两个运算符都归类为逻辑运算符,并区分按位逻辑和布尔逻辑:msdn.microsoft.com/en-us/library/6a71f45d(v=vs.100).aspx
      【解决方案8】:

      对于布尔值不是很多

      但是对于位标志,这可以允许这样的代码:

      int flags=0;
      flags|=READ;
      //flags|=UPDATE;
      foo(arg,flags);
      

      这允许一些标志很容易被注释掉(并使使用的标志在 IMO 中更具可读性)

      【讨论】:

        【解决方案9】:

        这相当于

        tmp = tmp | true;
        

        编辑: 等于

        tmp = true;
        

        我同意这里的其他海报......!

        更多信息here

        【讨论】:

          【解决方案10】:

          它是一个使用 |= 赋值运算符的表达式。检查MSDN

          【讨论】:

          • 是的,我查看并理解它只是没有意义,他们在我拥有的代码中使用它。
          猜你喜欢
          • 2010-09-06
          • 1970-01-01
          • 1970-01-01
          • 2013-02-27
          • 1970-01-01
          • 1970-01-01
          • 2012-02-20
          • 2012-02-19
          • 1970-01-01
          相关资源
          最近更新 更多