繁体   English   中英

&在C#中具有枚举值的运算符

[英]& operator with enum values in C#

我有以下代码,即使两个枚举表达式中都不存在Bottom ,但Console.WriteLine返回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
};

您为枚举赋值,运算符| &处理枚举值,就像它们将处理对应的值一样。

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

Right | Top
    1 |   2  (integer value)
   01 |  10  (bitwise representation)
   11        (taking the bitwise or)
Bottom

因此,这意味着,如果您编写& ,则这是按位AND ,而| ,是按位或在枚举值的

因此,如果现在评估它,我们将得到:

(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视为独立元素,因为我们找不到单调的按位构造(将LeftRightTop以构造Bottom (除法除外)。

为了使flag枚举能够按预期工作,枚举常量必须为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
}

是&和| 按位运算。 在示例中:

(( 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。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM