这可能是一个简单而简单的问题,但我仍然有点混淆按位OR
决定使用的原因。假设我有一个包含四个字段的课程A
:
class A
{
private int Field1;
private static int Field2;
public int Field3;
public static int Field4;
}
使用Reflection
获取字段:
var fields = typeof (A).GetFields(BindingFlags.Public | BindingFlags.Static);
如果你是Reflection
的新手并且不知道如何使用BindingFlags
,那么你头脑中最初的逻辑思维就是:
此行将选择所有静态OR公共字段,因为使用了按位OR。你想到的预期结果是:
Field2
Field3
Field4
但是当按下F5时,结果将完全不同,按位OR
可用作AND
:
Field4
为什么不使用可能跟随逻辑思维的按位AND运算符。像这样:
var fields = typeof (A).GetFields(BindingFlags.Public & BindingFlags.Static);
我在MSDN中找到了单词:
用于组合标志的按位OR运算在某些情况下可能被认为是一个高级概念,对于简单任务而言并不是必需的。
请允许任何人以简单的方式解释高级概念以便理解吗?
答案 0 :(得分:25)
请参阅最后的摘要。
答案很长:
按位OR组合枚举标志的位。
示例:
BindingFlags.Public
的值为16或10000(二进制)BindingFlags.Static
的值为8或1000(二进制)按位OR组合如下:
10000
01000
--
11000 --> 24
按位AND将它们组合起来:
10000
01000
--
00000 --> 0
这是Flags的一个非常基本的概念:
每个值都是2的幂,例如:
2^0
2^1
2^2
2^3
它们的位表示始终为1
,其余为0:
decimal | binary
1 | 0001
2 | 0010
4 | 0100
8 | 1000
使用按位AND组合它们中的任何一个将始终导致0,因为在同一位置没有1
。按位AND将导致完整的信息丢失。
另一方面,按位OR将始终产生明确的结果。例如,当你有(二进制)1010(十进制10)时,你知道它原来是8和2.没有其他可能性10可以创建。
正如默认所述,您调用的方法稍后可以使用按位AND运算符提取此信息:
if(10 & 8 == 8) // value 8 was set
在这种情况下,按位OR基本上是将值传输到您正在呼叫的方法的工具。
这种方法对这些值的作用与按位OR的使用无关
它可以内部要求所有传递的标志匹配,就像GetFields
的情况一样。但它也可能只需要一个传递的标志匹配。
对于您作为来电者,以下内容是等效的:
var requiredFlags = new List<BindingFlags>();
requiredFlags.Add(BindingFlags.Public);
requiredFlags.Add(BindingFlags.Static);
typeof (A).GetFields(requiredFlags);
现在不编译为GetFields
不会提供这样的重载,但其含义与代码的含义相同。
总结(TL; DR):
按位AND与布尔AND和无关 按位OR与布尔OR
无关答案 1 :(得分:2)
标志枚举用于表示一组布尔条件。
在您的示例中,必须满足每个布尔条件才能返回相应的字段。
标志枚举只是符合通常的二进制规则的整数值,因此要设置几个位,必须将表示这些位的值一起OR。
完成此操作后,您将拥有一个标记枚举,并设置相应的位。
您遇到的问题是因为您正在混淆两个不同的概念:为标志枚举构造布尔条件集的方式是一个概念。使用标志枚举(或它代表什么)的方式是一个不同的概念。
前者使用OR来构造一组布尔条件。后者表示每个位代表必须满足的布尔条件。
答案 2 :(得分:1)
GetFields()的实现者选择解释各种ORed标志的组合,这意味着所选标准的AND组合。
这是有道理的,因为如果您不想要额外的过滤器,您可以随时删除标准。