&安培;具有C#中枚举值的运算符

时间:2017-12-01 17:28:54

标签: c# enums

我有以下代码,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
};

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
};

现在你可以看到枚举为四个不同的标志,并且&将创建交集,|标志的并集。在评论中,写入每个值的按位表示。

如您所见,我们现在可以将LeftRightTopBottom视为独立元素,因为我们无法找到单调< / em>按位构造(将LeftRightTop结合起来构建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。