2016-11-16 118 views
2

有我色彩選擇enum代表紅,藍,綠,無。枚舉位運算返回錯誤值

[Flags] 
public enum SelectedColor 
{ 
    None, Red, Blue, Green 
} 

當我創建一個新的枚舉並將其設置爲RedGreen然後檢查是否Blue設置,返回trueBlue從來沒有設置任何地方。

例如:

SelectedColor selectedColor = SelectedColor.Red; 
selectedColor |= SelectedColor.Green; //Add Green to Selection 

//Check if blue is set 
Debug.Log("Blue Selected hasFlag? : " + hasFlag(selectedColor, SelectedColor.Blue)); 

//Check if blue is set 
Debug.Log("Blue Selected isSet? : " + isSet(selectedColor, SelectedColor.Blue)); 

輸出:

藍中選出的hasFlag? :False

Blue Selected isSet? :真

hasFlag和isSet功能:

bool hasFlag(SelectedColor source, SelectedColor value) 
{ 
    int s1 = (int)source; 
    return Convert.ToBoolean((s1 & Convert.ToInt32(((int)value) == s1))); 
} 


bool isSet(SelectedColor source, SelectedColor critValue) 
{ 
    //return ((source & critValue) == critValue); 
    return ((source & critValue) != 0); 
} 

正如你看到的,我的isSet函數返回錯誤值。我已經嘗試了return ((source & critValue) == critValue)return ((source & critValue) != 0);,但他們都失敗了。這應該根據我對SO和this後的研究。

hasFlag功能是好的,但爲什麼是isSet函數返回錯誤的值?

請注意,我使用.NET 3.5,所以我不能使用.NET 4枚舉幫助函數,如HasFlag

回答

9

如果沒有指定枚舉值,序列號分配給他們,像這樣:

[Flags] 
public enum SelectedColor // WRONG 
{ 
    None = 0, // 000 
    Red = 1, // 001 
    Blue = 2, // 010 
    Green = 3 // 011 <-- Not the next power of two! 
} 

然後出現這種情況:

selectedColor = SelectedColor.Red; // 001 
selectedColor |= SelectedColor.Green; // (001 | 011) == 011, which is still Green 

您需要使用的兩個大國爲[Flags]枚舉,如下所示:

[Flags] 
public enum SelectedColor // CORRECT 
{ 
    None = 0, // 000 
    Red = 1, // 001 
    Blue = 2, // 010 
    Green = 4 // 100 
} 

然後它工作正常:

selectedColor = SelectedColor.Red; // 001 
selectedColor |= SelectedColor.Green; // (001 | 100) == 101, which is Red, Green 
+1

+1。值得指出的是,如果顯式值沒有被定義,則從0,1,2,3,4等順序排列。其次,Flags屬性不會影響默認情況下創建值的方式。它確實會影響'ToString'的行爲,並且還會向IDE發信號通知枚舉是否打算用作標誌。 – vcsjones

+0

@vcsjones好點,我會補充說。 –

+0

我試過這個enum btiwise操作並放棄了。現在,我回來才發現我必須爲枚舉提供值。那麼,在4之後,下一個是8? – Programmer

1

即使馬修的答案是正確的,這是一個很好的答案(有題目here的「刷爆版」),我會保持它的「通用」,有點更簡單走另一條路:與圖層蒙版一樣的行爲。這裏的限制,你的枚舉不能超過32個項目,但。

private void uncleFoo() { 
    enum myNATO { Adam, Bravo, Charlie, Delta } //my enum with NATO codes 
    int activeNATO = 0; //int to store selected NATO codes 

    //some testing here 
    activeNATO |= 1 << (int)myNATO.Adam; 
    activeNATO |= 1 << (int)myNATO.Bravo; 
    activeNATO |= 1 << (int)myNATO.Charlie; 
    Debug.Log(activeNATO); 
    Debug.Log("has Adam? " + (activeNATO & 1 << (int)myNATO.Adam)); 
    Debug.Log("has Delta? " + (activeNATO & 1 << (int)myNATO.Delta)); 
}

Debug.Log將顯示Adam爲「1」,顯然爲「Delta」顯示「0」。

希望這有助於;)