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

C# &;C中具有枚举值的运算符#,c#,enums,C#,Enums,我有以下代码和控制台。WriteLine返回Bottom,即使Bottom不在两个枚举表达式中 void Main() { Console.WriteLine(( Orientations.Left | Orientations.Bottom) & (Orientations.Right| Orientations.Top));//returns Bottom } [Flags] public enum Orientations {

我有以下代码和
控制台。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
};
问题

下面给出的代码段中返回Bottom的逻辑是什么?我对&operator的理解是,它返回公共部分,但在本例中,两个枚举表达式之间没有任何公共部分

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
    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
};
[标志]
公共枚举方向{
左=1,//0001
右=2,//0010
Top=4,//0100
底部=8//1000
};
现在,您可以将枚举视为四个不同的标志,
&
将创建交叉点,
|
将创建标志的并集。在注释中,写入每个值的位表示


正如您所看到的,我们现在可以将
视为独立元素,因为我们无法找到单调的按位构造(将
组合在一起构造
(否定除外).

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

您自己设置了枚举值的值,但没有将它们设置为正交。由于整数实际上是位字符串(具有固定长度),因此可以将其视为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
};
[标志]
公共枚举方向{
左=1,//0001
右=2,//0010
Top=4,//0100
底部=8//1000
};
现在,您可以将枚举视为四个不同的标志,
&
将创建交叉点,
|
标志的并集。在注释中,将写入每个值的按位表示


正如您所看到的,我们现在可以将
视为独立元素,因为我们无法找到单调的按位构造(将
组合在一起构造
(否定除外).

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

(( 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.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,int值是Orientations.Bottom值。因此,它总是返回Orientations.Bottom。

为了使标志枚举按预期工作,枚举常量必须是2的幂

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

如果你选择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
};
请注意,每个枚举都有一个从0的隐式转换。因此,您可以执行此测试

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

为了使标志枚举按预期工作,枚举常量必须是2的幂

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

如果你选择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
};
请注意,每个枚举都有一个从0的隐式转换。因此,您可以执行此测试

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

(0 | 3)和(1 | 2)
=
3
。枚举只是“整型”值的语法糖。您可以在两个不同的枚举之间进行强制转换,编译器不会抱怨——即使一个枚举有另一个枚举没有的值。谢谢。根据MSDN文档,它说
按位and运算符(&)将第一个操作数的每个位与第二个操作数的相应位进行比较。如果两个位都为1,则相应的结果位设置为1。否则,相应的结果位设置为0。
,它是否应仅返回0或1而不是3?这里的问题是枚举未正确设置为2的幂,因此值为ar代表