我有以下代码,Console.WriteLine
正在返回Bottom
,即使Bottom不在两个枚举表达式中。
问题
在下面给出的代码片段中返回Bottom背后的逻辑是什么?我对&的理解运算符是它返回公共部分,但在这种情况下,两个枚举表达式之间没有任何共同之处。
void Main()
{
Console.WriteLine(( Orientations.Left | Orientations.Bottom) &
(Orientations.Right| Orientations.Top));//returns Bottom
}
[Flags]
public enum Orientations {
Left = 0, Right= 1, Top=2, Bottom =3
};
答案 0 :(得分:7)
您可以为枚举值指定值,运算符|
和&
可以处理枚举值,就像它们可以处理相应的值一样。
您已自行设置枚举值的值,但尚未将它们设置为正交。由于整数实际上是位串(具有固定长度),因此您可以将其视为32维向量(每个向量元素都具有域{0,1}
)。由于您将实例Bottom
定义为3
,这意味着Bottom
实际上等于Right | Top
,因为:
Right | Top
1 | 2 (integer value)
01 | 10 (bitwise representation)
11 (taking the bitwise or)
Bottom
这意味着如果你写 &
,这是按位AND , |
,在枚举值的值上是按位OR 。
因此,如果我们现在评估它,我们得到:
(Orientations.Left|Orientations.Bottom) & (Orientations.Right|Orientations.Top)
(0 | 3 ) & (1 | 2)
3 & 3
3
Orientations.Bottom
如果要定义四个正交值,则需要使用两个幂:
[Flags]
public enum Orientations {
Left = 1, // 0001
Right = 2, // 0010
Top = 4, // 0100
Bottom = 8 // 1000
};
现在你可以看到枚举为四个不同的标志,并且&
将创建交集,|
标志的并集。在评论中,写入每个值的按位表示。
如您所见,我们现在可以将Left
,Right
,Top
和Bottom
视为独立元素,因为我们无法找到单调< / em>按位构造(将Left
,Right
和Top
结合起来构建Bottom
(除了否定)。
答案 1 :(得分:3)
为了使标志枚举按预期工作,枚举常量必须是2的幂。
在您的示例中,二进制值看起来像这样(为简单起见,我只显示4位)
Left = 0 0000
Right = 1 0001
Top = 2 0010
Bottom = 3 0011
Left | Right | Top | Bottom = 0011 which is 3 or Bottom again
如果您选择2的权力,则
Left = 1 = 2^0 0001
Right = 2 = 2^1 0010
Top = 4 = 2^2 0100
Bottom = 8 = 2^3 1000
Left | Right | Top | Bottom = 1111
即,功率为2时,设置不同的位,因此它们与按位OR运算符(|)整齐地结合在一起。
从C#7.0开始,您可以使用二进制文字
[Flags]
public enum Orientations {
Left = 0b0001,
Right = 0b0010,
Top = 0b0100,
Bottom = 0b1000
};
在以前版本的C#中,您还可以使用左移运算符来获得2的幂
[Flags]
public enum Orientations {
Left = 1 << 0,
Right = 1 << 1,
Top = 1 << 2,
Bottom = 1 << 3
};
最好还包括枚举常量None = 0
,因为枚举字段初始化为default(MyEnum) == 0
,否则会导致值没有相应的枚举常量。
您还可以创建新的组合枚举值,例如
[Flags]
public enum Orientations {
None = 0,
Left = 1 << 0,
Right = 1 << 1,
Top = 1 << 2,
Bottom = 1 << 3,
Horizontal = Left | Right,
Vertical = Top | Bottom,
All = Horizontal | Vertical
};
请注意,每个枚举都有一个0的隐式转换。因此,您可以执行此测试
if((myOrientations & Orientations.Vertical) != 0) {
// We have at least a Top or Bottom orientation or both
}
答案 2 :(得分:1)
它是&amp;和|按位运算。在示例中:
(( Orientations.Left | Orientations.Bottom) &
(Orientations.Right| Orientations.Top))
将替换为
((0 | 3) & (1 | 2)) with in bit (show only last 3 bit):
((000 |011) & (001 | 010))
= (011 & 011)
= 011
011是int值中的3,即Orientations.Bottom值。因此,它始终返回Orientations.Bottom。