What Does the [Flags] Enum Attribute Mean in C#

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

The [Flags] attribute should be used whenever the enumerable represents a collection of possible values, rather than a single value. Such collections are often used with bitwise operators, for example:

var allowedColors = MyColor.Red | MyColor.Green | MyColor.Blue;

Note that the [Flags] attribute doesn't enable this by itself - all it does is allow 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, // 0
Green, // 1
Red, // 2
Blue // 3
}

The values, if declared this way, will be Yellow = 0, Green = 1, Red = 2, Blue = 3. This will render it useless 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 your property, one can do this:

if (myProperties.AllowedColors.HasFlag(MyColor.Yellow))
{
// Yellow is allowed...
}

or prior to .NET 4:

if((myProperties.AllowedColors & MyColor.Yellow) == MyColor.Yellow)
{
// Yellow is allowed...
}

if((myProperties.AllowedColors & MyColor.Green) == MyColor.Green)
{
// Green is allowed...
}

Under the covers

This works because you used powers of two in your enumeration. Under the covers, your enumeration values look like this in binary ones and zeros:

 Yellow: 00000001
Green: 00000010
Red: 00000100
Blue: 00001000

Similarly, after you've set your property AllowedColors to Red, Green and Blue using the binary bitwise OR | operator, AllowedColors looks like this:

myProperties.AllowedColors: 00001110

So when you retrieve the value you are actually performing bitwise AND & on the values:

myProperties.AllowedColors: 00001110
MyColor.Green: 00000010
-----------------------
00000010 // Hey, this is the same as MyColor.Green!

The None = 0 value

And regarding the use of 0 in your 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

How does c# flags attribute enum bit combining work?

It's not about banning or allowing combinations or bitwise operators (either is allowed with or without the Flags attribute) as indicating that bitwise makes sense, and affecting how ToString() works.

Consider:

public enum Color
{
Black = 0,
Blue = 1,
Green = 2,
Red = 4
}

This would allow us to meaningfully talk about 8 colours, depending on whether the given blue, green or red flags were set.

We could define these combinations within the enum:

public enum Color
{
Black = 0,
Blue = 1,
Green = 2,
Cyan = 3,
Red = 4,
Magenta = 5,
Yellow = 6,
White = 7
}

Note that here the functionality is the same: Color.Green | Color.Red has the same value of 6 either way, which of course would indicate yellow. The difference is in whether we give it the convenient label of Yellow or not.

The main difference between my enum and yours is that my combinations make some sort of general sense, because green and red light mix to make yellow, and so on. Generally we'll only find it useful to name the 1-bit only values (1, 2, 4, 8…) but sometimes naming particular common combinations is useful to the coder who is using the enum. A real example of this is DateTimeStyles. In that enum, AllowLeadingWhite has a value of 1, AllowTrailingWhite has a value of 2, AllowInnerWhite has a value of 4, and AllowWhiteSpaces has a value of 7 as a convenient way to indicate all of those three flags are set.

Flags and operation on enums? C#

Behind the scenes, the enumeration is actually an int.

<< is the Bitwise Left Shift Operator

An equivalent way of writing this code is :

[Flags]
public enum EAccountStatus
{
None = 0,
FreeServiceApproved = 1,
GovernmentAccount = 2,
PrivateOrganisationAccount = 4,
All = 8
}

Please note, that this enumeration has the Flag attribute

As stated in the msdn:

Use the FlagsAttribute custom attribute for an enumeration only if a
bitwise operation (AND, OR, EXCLUSIVE OR) is to be performed on a
numeric value.

This way, if you want to have multiple options set you can use:

var combined =  EAccountStatus.FreeServiceApproved  | EAccountStatus.GovernmentAccount 

which is equivalent to:

  00000001  // =1 - FreeServiceApproved 
| 00000010 // =2 - GovernmentAccount
---------
00000011 //= 3 - FreeServiceApproved and GovernmentAccount

this SO thread has a rather good explanation about the flags attribute

What is the reason for marking an enum with the [Flags] attribute?

Resharper isn't recommending that ConvertStatus.Running receive an attribute, but the entire ConvertStatus enum.

From MSDN, FlagsAttribute is described as:

Indicates that an enumeration can be treated as a bit field; that is, a set of flags.

Since you are using bitwise operations on an enum that isn't indicated to actually be usable as a bit field, R# is warning you that your code may have unintended effects at run time. Using the [Flags] attribute itself doesn't guarantee that the implementation of the enum is actually consistent with the values expected for a bit field, but it does create a contract that the outside world should expect it to be.

enum with flags attribute

Enum has method HasFlag to determine whether one or more bit fields are set in the current instance.

CLR - Declare enum with Flags attribute

The FlagsAttribute in C# just indicates that the enumeration can be treated as a bit field.

What really matters is that you define the enumeration values appropriately so that AND, OR, NOT and XOR bitwise operations can be performed on them, i.e. you should assign each enumeration value the next greater power of 2:

public enum class Days
{
Sunday = 1,
Monday = 2,
Tuesday = 4,
Wednesday = 8,
Thursday = 16,
Friday = 32,
Saturday = 64
};

[Flags] does not automatically make the enum values powers of two.

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

C# using [Flags] with [Description]

In order to produce the result you are looking for, use the following code:

public static String GetDescription(ReasonCode reasonCode)
{
if (reasonCode == ReasonCode.None)
return "Verified";

StringBuilder sb = new StringBuilder();
sb.AppendLine("Failed:");

foreach (ReasonCode rc in Enum.GetValues(typeof(ReasonCode)).Cast<ReasonCode>())
{
if (rc == ReasonCode.None)
continue;

if (reasonCode.HasFlag(rc))
sb.AppendLine(rc.ToString() + " - " + GetEnumDescription(rc));
}

return sb.ToString();
}

The code used to retrieve the description value is based on this implementation:

public static String GetEnumDescription(Enum value)
{
String valueText = value.ToString();
Type type = value.GetType();

FieldInfo fi = type.GetField(valueText);
Object[] attributes = fi.GetCustomAttributes(typeof(DescriptionAttribute), false);

if (attributes.Length > 0)
{
DescriptionAttribute attribute = (DescriptionAttribute)attributes[0];
return attribute.Description;
}

return valueText;
}

You can find a working demo here.

Problems with Enum as Flags

You need to define the enum constants as powers of two.

[Flags]
public enum Status
{
Nominal = 1,
Modified = 2,
DirOneOnly = 4,
DirTwoOnly = 8,
DirOneNewest = 16,
DirTwoNewest = 32
}

class Program
{
static void Main(string[] args)
{
Status s = new Status();
s |= Status.Modified;
if (s.HasFlag(Status.Modified))
{
Console.WriteLine("Modified!");
}
}
}

What Does the [Flags] Attribute Really Do?

From an MSDN article:

It is interesting to note that when
Flags is specified, Parse and Format
methods feature advanced capabilities.

Likewise, the Parse method can
successfully parse a comma-separated
string like the one just shown into
the proper numeric value.



Related Topics



Leave a reply



Submit