Programmer Programmer - 24 days ago 6
C# Question

Enum Bitwise operation returning wrong value

I have color selection

enum
that represents Red, Blue, Green and None.

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


When I create a new enum and set it to
Red
and
Green
then check if
Blue
is set, it returns
true
.
Blue
was never set anywhere.

For example:

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));


Output:


Blue Selected hasFlag? : False

Blue Selected isSet? : True


hasFlag and isSet function:

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);
}


As you can see, my
isSet
function is returning the wrong value. I have tried both
return ((source & critValue) == critValue)
and
return ((source & critValue) != 0);
in it but they both still failed. This should work according to my research on SO and this post.

My
hasFlag
function is fine but why is the
isSet
function returning the wrong value?

Please note that I am using .NET 3.5, so I can't use .NET 4 enum helper functions such as
HasFlag
.

Answer

If you do not specify values for enums, sequential numbers are assigned to to them like so:

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

Then this happens:

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

You need to use powers of two for [Flags] enums, as follows:

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

Then it works correctly:

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