Anyone have a good explanation or example they could post?
Edit: I changed the answer, this one is more in depth.
Anyone have a good explanation or example they could post?
Edit: I changed the answer, this one is more in depth.
Definition
[Flags]
public enum Color
{
Red, White, Blue
}
Usage
Color norwegianFlag = Color.Red | Color.White | Color.Blue
Use the [Flags] attribute to specify that you can combine its members.
Further reading: Enum values as bit flags - using FlagsAttribute
Please see the following for an example which shows the declaration and potential usage:
namespace Flags
{
class Program
{
[FlagsAttribute]
public enum MyFlags : short
{
Foo = 0x1,
Bar = 0x2,
Baz = 0x4
}
static void Main(string[] args)
{
MyFlags fooBar = MyFlags.Foo | MyFlags.Bar;
if ((fooBar & MyFlags.Foo) == MyFlags.Foo)
{
Console.WriteLine("Item has Foo flag set");
}
}
}
}
You can also do this
[Flags]
public enum MyEnum
{
None = 0,
First = 1,
Second = 1 << 1,
Third = 1 << 2,
Fourth = 1 << 3
}
I find the bit-shifting easier than typing 4,8,16,32 and so on. It has no impact on your code because it's all done at compile time
The flags attribute should be used only when bitwise operations (and, or, exclusive or, not) is to be used on the enum. One example is
myProperties.AllowedColors = MyColor.Red | MyColor.Green | MyColor.Blue;
This will render the posibility to retrieve these three distinct values from your property AllowedColors.
For this to work the values in your enumeration need to be powers of two (as seen in Jay Mooneys example)
[Flags]
public enum MyColor
{
Yellow = 1,
Green = 2,
Red = 4,
Blue = 8
}
To retrieve the distinct values in you property one can do this
if((myProperties.AllowedColors & MyColor.Yellow) == MyColor.Yellow)
{
// Yellow has been set...
}
if((myProperties.AllowedColors & MyColor.Green) == MyColor.Green)
{
// Green has been set...
}
Under the covers
This works because you previously used multiples of two in you enumeration. Under the covers your enumeration values looks like this (presented as bytes, which has 8 bits which can be 1's or 0's)
Yellow: 00000001
Green: 00000010
Red: 00000100
Blue: 00001000
Likewise, after you've set your property AllowedColors to Red, Green and Blue (which values where OR'ed by the pipe |), AllowedColors looks like this
myProperties.AllowedColors: 00001110
So when you retreive the value you are actually bitwise AND'ing the values
myProperties.AllowedColors: 00001110
MyColor.Green: 00000010
-----------------------
00000010 // Hey, this is the same as MyColor.Green!
The None = 0 value
And regarding use 0 in you enumeration, quoting from msdn:
[Flags]
public enum MyColor
{
None = 0,
....
}
Use None as the name of the flag enumerated constant whose value is zero. You cannot use the None enumerated constant in a bitwise AND operation to test for a flag because the result is always zero. However, you can perform a logical, not a bitwise, comparison between the numeric value and the None enumerated constant to determine whether any bits in the numeric value are set.
You can find more info about the flags attribute and its usage at msdn and designing flags at msdn
@Nidonocu
To add another flag to an existing set of values, use the OR assignment operator.
Mode = Mode.Read;
//Add Mode.Write
Mode |= Mode.Write;
Assert.True(((Mode & Mode.Write) == Mode.Write)
&& ((Mode & Mode.Read) == Mode.Read)));
I asked recently about something similar.
If you use flags you can add an extension method to enums to make checking the contained flags easier (see post for detail)
This allows you to do:
[Flags]
public enum PossibleOptions : byte
{
None = 0,
OptionOne = 1,
OptionTwo = 2,
OptionThree = 4,
OptionFour = 8,
//combinations can be in the enum too
OptionOneAndTwo = OptionOne | OptionTwo,
OptionOneTwoAndThree = OptionOne | OptionTwo | OptionThree,
...
}
Then you can do:
PossibleOptions opt = PossibleOptions.OptionOneTwoAndThree
if( opt.IsSet( PossibleOptions.OptionOne ) ) {
//optionOne is one of those set
}
I find this easier to read than the most ways of checking the included flags.
For this to work the values in your enumeration need to be multiples of two
This is not correct. The values need to be powers of two.
What am I missing here? Since enum's are (per default) using int to store the value, standard bitwise operations have always worked without [flags], like this:
enum MyEnum
{
enum1 = 1,
enum2 = 2,
enum4 = 4
}
private void testBitwiseEnums()
{
MyEnum result = MyEnum.enum1 | MyEnum.enum2;
if ((result & MyEnum.enum2) == MyEnum.enum2)
{
//this will happen
}
if ((result & MyEnum.enum4) == MyEnum.enum4)
{
//this will NOT happen
}
result |= MyEnum.enum4;
if ((result & MyEnum.enum4) == MyEnum.enum4)
{
//this will happen
}
result &= ~MyEnum.enum4;
if ((result & MyEnum.enum4) == MyEnum.enum4)
{
//this will NOT happen
}
}
no?