&运算符,带有C#中的枚举值

Sun*_*nil 0 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
};
Run Code Online (Sandbox Code Playgroud)

Wil*_*sem 8

你赋值的枚举,以及运营商|和&上枚举值的工作,像他们将在相应的值工作.

您自己设置了枚举值的值,但尚未将它们设置为正交值.由于整数实际上是位串(具有固定长度),因此您可以将其视为32维向量(每个向量元素都具有域{0,1}).既然你的实例定义Bottom为3,这意味着Bottom实际上是等于Right | Top,因为:

Right | Top
    1 |   2  (integer value)
   01 |  10  (bitwise representation)
   11        (taking the bitwise or)
Bottom
Run Code Online (Sandbox Code Playgroud)

这意味着如果你写&,这是一个按位AND,并且|是枚举值的值的按位OR.

所以,如果我们现在评估它,我们得到:

(Orientations.Left|Orientations.Bottom) & (Orientations.Right|Orientations.Top)
(0                | 3                 ) & (1                 | 2)
3                                       & 3
3
Orientations.Bottom
Run Code Online (Sandbox Code Playgroud)

如果要定义四个正交值,则需要使用两个幂:

[Flags]
public enum Orientations {
    Left = 1,    // 0001
    Right = 2,   // 0010
    Top = 4,     // 0100
    Bottom = 8   // 1000
};
Run Code Online (Sandbox Code Playgroud)

现在,您可以将枚举看作四个不同的标志,并且&将创建交集和|标志的并集.在注释中,写入每个值的按位表示.

正如你所看到的,我们现在可以看到Left,Right,Top并Bottom作为独立的元素,因为我们无法找到一个单调的逐位结构(结合Left,Right并Top构建Bottom(除了否定).

  • /sf/ask/413207721/ Flags确实做了些什么,也许不是人们的想法.如果枚举是这样的,那么它应该有`[Flags]` (2认同)

Oli*_*bes 8

为了使标志枚举按预期工作,枚举常量需要是 2 的幂。

在您的示例中,二进制值如下所示(为了简单起见,我仅显示 4 位)

Left   = 0                     0000
Right  = 1                     0001
Top    = 2                     0010
Bottom = 3                     0011
Left | Right | Top | Bottom =  0011 which is 3 and equal to Bottom 
Run Code Online (Sandbox Code Playgroud)

如果您选择 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 
Run Code Online (Sandbox Code Playgroud)

即,对于 2 的幂,设置了不同的位,因此它们与按位或运算符 (|) 巧妙地结合在一起。

从 C# 7.0 开始,您可以使用二进制文字

[Flags]
public enum Orientations {
    Left   = 0b0001,
    Right  = 0b0010,
    Top    = 0b0100,
    Bottom = 0b1000
};
Run Code Online (Sandbox Code Playgroud)

在以前版本的 C# 中,您还可以使用左移运算符来获取 2 的幂

[Flags]
public enum Orientations {
    Left   = 1 << 0,
    Right  = 1 << 1,
    Top    = 1 << 2,
    Bottom = 1 << 3
};
Run Code Online (Sandbox Code Playgroud)

最好还包含枚举常量,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
};
Run Code Online (Sandbox Code Playgroud)

请注意,每个枚举都有从 0 开始的隐式转换。因此您可以进行此测试

if((myOrientations & Orientations.Vertical) != 0) {
    // We have at least a Top or Bottom orientation or both
}
Run Code Online (Sandbox Code Playgroud)