Brian Leahy Brian Leahy - 3 months ago 20
C# Question

What does the [Flags] Enum Attribute mean in C#?

From time to time I see an enum like the following:

[Flags]
public enum Options
{
None = 0,
Option1 = 1,
Option2 = 2,
Option3 = 4,
Option4 = 8
}


I don't understand what exactly the
[Flags]
-attribute does.

Anyone have a good explanation or example they could post?

Answer

The flags attribute should be used whenever the enumerable represents a collection of flags, rather than a single value. Such collections are usually manipulated using bitwise operators, for example:

myProperties.AllowedColors = MyColor.Red | MyColor.Green | MyColor.Blue;

Note that [Flags] by itself doesn't change this at all - all it does is enable a nice representation by the .ToString() method:

enum Suits { Spades = 1, Clubs = 2, Diamonds = 4, Hearts = 8 }
[Flags] enum SuitsFlags { Spades = 1, Clubs = 2, Diamonds = 4, Hearts = 8 }

...

var str1 = (Suits.Spades | Suits.Diamonds).ToString();
           // "5"
var str2 = (SuitsFlags.Spades | SuitsFlags.Diamonds).ToString();
           // "Spades, Diamonds"

It is also important to note that [Flags] does not automatically make the enum values powers of two. If you omit the numeric values, the enum will not work as one might expect in bitwise operations, because by default the values start with 0 and increment.

Incorrect declaration:

[Flags]
public enum MyColors
{
    Yellow,
    Green,
    Red,
    Blue
}

The values, if declared this way, will be Yellow = 0, Green = 1, Red = 2, Blue = 3. This will render it useless for use as flags.

Here's an example of a correct declaration:

[Flags]
public enum MyColors
{
    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...
}    

or, in .NET 4 and later,

if (myProperties.AllowedColors.HasFlag(MyColor.Yellow))
{
    // Yellow has been set...
}

Under the covers

This works because you previously used powers 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 MyColors
{
    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

Comments