Enum按位操作返回错误值

本文关键字:错误 返回 位操作 Enum | 更新日期: 2023-09-27 18:18:18

我有颜色选择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));
输出:

Blue Selected hasFlag?:假

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和这篇文章的研究,这应该是可行的。

我的hasFlag函数很好,但为什么isSet函数返回错误的值?

请注意,我正在使用。net 3.5,所以我不能使用。net 4枚举辅助函数,如HasFlag .

Enum按位操作返回错误值

如果未为枚举指定值,则为其分配序号,如下所示:

[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]枚举使用2的幂,如下所示:

[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 

尽管Matthew的答案是正确的,这是一个非常好的答案(这里有一个主题的"最大化版本"),我会保持它的"通用"和更简单一点,走另一种方式:与图层蒙版使用相同的行为。这里的限制是,枚举不能有超过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",很明显。