为啥要在 C# 中对布尔值使用 |= 运算符?

Posted

技术标签:

【中文标题】为啥要在 C# 中对布尔值使用 |= 运算符?【英文标题】: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 在其示例中列出了一个布尔值和|= 运算符... 【参考方案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

【讨论】:

是的,我查看并理解它只是没有意义,他们在我拥有的代码中使用它。

以上是关于为啥要在 C# 中对布尔值使用 |= 运算符?的主要内容,如果未能解决你的问题,请参考以下文章

在 C++ 中对布尔值使用位运算符

正经学C#_布尔运算[布尔值与其布尔运算符]:《c#入门经典》

为啥 ~(true^true) 不正确?布尔运算符(否定)适用于“无符号字符”,但不适用于布尔值? (C++)

速记布尔值

在 C# 中对布尔值使用 &=

为啥析取赋值运算符 |= 不适用于布尔向量?