2013-07-26 48 views
39

我一直在寻找在目前,我有我的项目中的代码,发现是这样的:为什么有人在枚举声明中使用<<运算符?

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

<<操作数是移位操作数,移动通过在第二个操作数指定的位数留下的第一个操作数。

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

+21

我不知道谁会投票结束这件事,但这不是一个“主要基于意见的”问题。这是一个技术性问题,具体询问'<<'在这种情况下的用途。 –

+0

@GrantWinney(不是我的票接近),但我看到它是如何“意见为基础的”,因为这个问题本质上是“为什么有人使用'1 << 2'时'0x04'更具有可读性*我*”。 –

+7

我从来没有说过0x04更具可读性,我也没有比较过。这个问题的目的是了解这句话的副作用(=能够标志结合使用) – JSBach

回答

40

这允许你做这样的事情:

var myEnumValue = MyEnum.open | MyEnum.close; 

无需计算的2

倍数位值(像这样):

public enum MyEnum 
{ 
    open  = 1, 
    close = 2, 
    Maybe = 4, 
    ........ 
} 
+1

**注意**:['<<'声明会给你最多达64个不同的状态(在大多数平台上)。如果您需要更多可能的状态,这种解决方案将无法正常工作(http://stackoverflow.com/questions/8956364/app-states-with-bool-flags?answertab=votes#8956606) –

+2

什么替代的解决方案将给予超过64个正交状态? – Useless

+2

@GrijeshChauhan大多数平台?这是C#,所以整数类型的大小不依赖于平台。 << <<'运算符的左操作数的类型决定了要使用哪个超载。例如,用's'表示一个整数,'1 << s'表示一个32位'int','1u << s'表示32位无符号'uint','1L << s'表示64位'long','1UL << s'是'ulong'和'(的BigInteger)1 << s'或'BigInteger.One << s'给出了一个任意大小的整数(需要参照'System.Numerics.dll '大会)。 –

22

这通常与位域使用,因为它是明确的模式是什么,就不再需要手动计算正确的价值观,从而降低它只是意味着是一个更清洁的错误

[Flags] 
public enum SomeBitField 
{ 
    open = 1 << 0 //1 
    closed = 1 << 1 //2 
    maybe = 1 << 2 //4 
    other = 1 << 3 //8 
    ... 
} 
+1

@RichardDeeming - 你当然是对的,谢谢。 – Lee

+0

我认为你的意思是按位操作,而不是位域。至少在C世界中,位域是子字节结构成员。 – noamtm

6

的机会/更直观的书写方式。 1,2,3是比0x1,0x2,0x4等更易读的序列。

10

为了避免手动输入Flags enum的值。

public enum MyEnum 
{ 
    open  = 0x01, 
    close = 0x02, 
    Maybe = 0x04, 
    ........ 
} 
+5

+1。人们可能会在这样的'enum'上标明'[Flags]来澄清用法......但不是每个人都在意。 –

6

这是使一个枚举,你可以结合。

什么它实际上意味着是这样的:

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

这仅仅是创建一个[Flags]枚举的更稳固的方法。

6

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

短版:

与其他组件进行交互和沟通 与其他工程师,因为它会告诉你明确什么位的字是 组或明确的而不是模糊内的信息时,该符号帮助数值。

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

龙版本:

传统的字位从右到左编号,从零开始。 所以最不重要的位是位数0,并且当你朝着最高位 进行计数。有几种benefits来标记位,这种方式是 。

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

另一个好处是,一个位的值是简单地提高到位 位的功率。例如,二进制0101具有第2位和第0位。位2贡献 值4 (2^2)到数字,位0贡献值1(2^0)。所以 数字的值当然是4 + 1 = 5.

这个冗长的背景解释让我们注意到:<<表示法只是通过查看它来告诉您位数。

本身在声明1 << n数字1是一个简单的单位当你左移这个数字,你再移动该设置 位的数量不同的位置 位位置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)

起初它可能看起来很古怪,但你会习惯的。如果你明确需要知道某些东西的位数,那么你会很感激它。

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);,它会做所有给定枚举值的东西。