Reputation: 125255
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
.
Upvotes: 2
Views: 587
Reputation:
Even though Matthew's answer is correct and it's a very good answer (there's a "maxed out version" of the topic here), I would keep it "generic" and a bit more simple and go another way: same behaviour used with Layer Masks. The limitation here, your enum can't have more than 32 items, though.
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 will print "1" for Adam, and "0" for Delta, obviously.
Hope this helps ;)
Upvotes: 1
Reputation: 109567
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
Upvotes: 9