2013-07-26 79 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);,它會做所有給定枚舉值的東西。