39

我正在查看我目前在我的项目中的代码,并发现了这样的内容:

public enum MyEnum
{
    open     = 1 << 00,
    close    = 1 << 01,
    Maybe    = 1 << 02,
    ........
}

操作数是移位操作数,它将第<<一个操作数左移第二个操作数中指定的位数。

但是为什么有人会在enum声明中使用它呢?

4

7 回答 7

40

这使您可以执行以下操作:

var myEnumValue = MyEnum.open | MyEnum.close;

无需计算 2 的倍数的位值。

(像这样):

public enum MyEnum
{
    open     = 1,
    close    = 2,
    Maybe    = 4,
    ........
}
于 2013-07-26T18:12:33.670 回答
22

这通常与位域一起使用,因为它很清楚模式是什么,消除了手动计算正确值的需要,从而减少了出错的机会

[Flags]
public enum SomeBitField
{
    open = 1 << 0    //1
    closed = 1 << 1  //2
    maybe = 1 << 2   //4
    other = 1 << 3   //8
    ...
}
于 2013-07-26T18:11:11.497 回答
10

避免Flags手动输入枚举的值。

public enum MyEnum
{
    open     = 0x01,
    close    = 0x02,
    Maybe    = 0x04,
    ........
}
于 2013-07-26T18:11:45.413 回答
6

这里有很多答案描述了这个机制允许你做什么,但不是你为什么要使用它。这就是为什么。

精简版:

在与其他组件交互和与其他工程师交流时,这种表示法会有所帮助,因为它明确地告诉您正在设置或清除单词中的哪个位,而不是在数值中隐藏该信息。

所以我可以打电话给你说“嘿,打开文件是什么位?” 你会说,“位 0”。我会写在我的代码open = 1 << 0中。因为右边的数字<<告诉你位数。

.

长版:

传统上,单词中的位从右到左编号,从零开始。因此,最低有效位是第 0 位,当您朝着最高有效位前进时,您会向上计数。以这种方式标记位有几个好处。

一个好处是,无论字长如何,您都可以谈论相同的内容。例如,我可以说在 32 位字 0x384A 和 8 位字 0x63 中,都设置了位 6 和 1。如果你在另一个方向编号你的位,你不能这样做。

另一个好处是位的值只是 2 的位位置的幂。例如,二进制0101设置了位 2 和 0。位 2 将值贡献4 (2^2)给数字,位 0 贡献值 1 (2^0)。所以这个数字的值当然是 4 + 1 = 5。

冗长的背景解释让我们明白了这一点:<<符号通过查看它就可以告诉您位数。

语句中的数字 1 本身1 << n只是位位置 0 中设置的单个位。当您将该数字左移时,您会将该设置位移动到该数字中的不同位置。方便的是,您移动的数量会告诉您将要设置的位数。

1 << 5:   This means bit 5.   The value is 0x20.
1 << 12:  This means bit 12.  The value is 0x40000.
1 << 17:  This means bit 17.  The value is 0x1000000.
1 << 54:  This means bit 54.  The value is 0x40000000000000.
          (You can probably see that this notation might be helpful if
          you're defining bits in a 64-bit number)

当您与另一个组件交互时,这种表示法真的很方便,例如将一个字中的位映射到硬件寄存器。就像您可能有一个设备在您写入第 7 位时打开。因此硬件工程师会编写一份数据表,说明第 7 位启用该设备。你会写在你的代码ENABLE = 1 << 7中。就这么简单。

哦拍。工程师刚刚向数据表发送了一个勘误表,说它应该是第 15 位,而不是第 7 位。没关系,只需将代码更改为 ENABLE = 1 << 15.

如果ENABLE实际上同时设置了第 7 位和第 1 位怎么办?

ENABLE = (1 << 7) | (1 << 1).

一开始它可能看起来很奇怪和迟钝,但你会习惯的。如果您明确需要知道某物的位数,您将不胜感激。

于 2013-07-26T22:12:31.997 回答
6

它只是为了成为一种更清洁/更直观的方式来编写这些位。1、2、3 是比 0x1、0x2、0x4 等更易于人类阅读的序列。

于 2013-07-26T18:11:43.077 回答
6

这是为了制作一个可以组合的枚举。

它的实际含义是:

public enum MyEnum
{
    open = 1;
    close = 2;
    Maybe = 4;
    //...
}

这只是创建[Flags]枚举的一种更防弹的方法。

于 2013-07-26T18:11:58.063 回答
0

它等于二的幂。

public enum SomeEnum
{
    Enum1 = 1 << 0,    //1
    Enum2 = 1 << 1,    //2
    Enum3 = 1 << 2,    //4
    Enum4 = 1 << 3     //8
}

使用这样的枚举,您将拥有如下所示的功能:

void foo(unsigned ind flags)
{
    for (int = 0; i < MAX_NUMS; i++)
        if (1 << i & flags)
        {
            //do some stuff...
            //parameter to that stuff probably is i either enum value
        }
}

并且调用该函数将是foo(Enum2 | Enum3);,它将对所有给定的枚举值执行某些操作。

于 2013-08-12T12:38:06.853 回答