为什么在带有含义AND的标志枚举中使用按位OR运算符

cuo*_*gle 13 .net c# c#-4.0

这可能是一个简单而简单的问题,但我仍然有点混淆bitwise OR决定使用的原因.假设我有一个A包含四个字段的类:

class A
{
    private int Field1;
    private static int Field2;
    public int Field3;
    public static int Field4;
}
Run Code Online (Sandbox Code Playgroud)

Reflection用来获取字段:

var fields = typeof (A).GetFields(BindingFlags.Public | BindingFlags.Static);
Run Code Online (Sandbox Code Playgroud)

如果你是新手,Reflection并且不知道如何使用BindingFlags,那么你头脑中最初的逻辑思维是:

此行将选择所有静态OR公共字段,因为使用了按位OR.你想到的预期结果:

Field2
Field3
Field4
Run Code Online (Sandbox Code Playgroud)

但是当击中F5时,结果将完全不同,按位的OR方式如下AND:

Field4
Run Code Online (Sandbox Code Playgroud)

为什么不使用可能跟随逻辑思维的按位AND运算符.像这样:

var fields = typeof (A).GetFields(BindingFlags.Public & BindingFlags.Static);
Run Code Online (Sandbox Code Playgroud)

我在MSDN中找到了单词:

在某些情况下,用于组合标志的按位OR运算可能被认为是一种高级概念,简单任务不应该这样做.

请允许任何人以简单的方式解释这里的先进概念以便理解吗?

Dan*_*rth 25

请参阅最后的摘要.

答案很长:

按位OR组合枚举标志的位.

例:

  • BindingFlags.Public 值为16或10000(二进制)
  • BindingFlags.Static 值为8或1000(二进制)

按位OR将这些组合如下:

10000
01000
--
11000  --> 24
Run Code Online (Sandbox Code Playgroud)

按位AND将它们组合如下:

10000
01000
--
00000   --> 0
Run Code Online (Sandbox Code Playgroud)

这是Flags的一个非常基本的概念:
每个值都是2的幂,例如:

  • 1 = 2^0
  • 2 = 2^1
  • 4 = 2^2
  • 8 = 2^3
  • 等等

它们的位表示始终为a 1,其余为0:

decimal | binary
1       | 0001
2       | 0010
4       | 0100
8       | 1000
Run Code Online (Sandbox Code Playgroud)

使用按位AND组合它们中的任何一个将始终导致0,因为1在相同位置没有.按位AND将导致完整的信息丢失.

另一方面,按位OR将始终产生明确的结果.例如,当你有(二进制)1010(十进制10)时,你知道它原来是8和2.没有其他可能性10可以创建.
如默认所述,您调用的方法可以稍后使用按位AND运算符提取此信息:

if(10 & 8 == 8) // value 8 was set
Run Code Online (Sandbox Code Playgroud)

在这种情况下,按位OR基本上是将值传输到您正在调用的方法的工具.
这种方法对这些值的作用与按位OR的使用无关.
它可以内部要求所​​有传递的标志匹配,如同GetFields.但它也可能只需要一个传递的标志匹配.

对于您作为调用者,以下内容将是等效的:

var requiredFlags = new List<BindingFlags>();
requiredFlags.Add(BindingFlags.Public);
requiredFlags.Add(BindingFlags.Static);
typeof (A).GetFields(requiredFlags);
Run Code Online (Sandbox Code Playgroud)

现在这不会编译,因为GetFields没有提供这样的重载,但其含义与您的代码的含义相同.

总结(TL; DR):

按位AND与布尔AND
无关或按位OR与布尔OR无关