Flags attribute for enums

Using the Flags attribute to treat an enum as a set of flags

Home DailyDrop

Daily Knowledge Drop

The Flags attribute can be used to automatically treat an enum as a set of flags (a bit field) - flags are useful when elements in the enum might occur in combinations.


Bitwise operations

Often an enum will have values of 0, 1, 2, 4, 8, 16 .. instead of 0, 1, 2, 3, 4, 5 .. - this is because it allows bitwise operations to be performed on the enum. Consider the following example enum used to indicate which destination(s) data should be published to:

enum PublishDestination : short
{
    None = 0,
    File = 1,
    Api = 2,
    Database = 4,
    Console = 8
};

To indicated that data should be published to multiple destinations, multiple values can be combined together - for example: 7 = 1 + 2 + 4 = File & Api & Database.

If 0, 1, 2, 3, 4, 5, 6 .. had been used, then 7 could be one of a few combinations:

  • 7 = 1 + 2 + 4
  • 7 = 1 + 6

Using 0, 1, 2, 4, 8, 16, .. allows for each number and each sum of numbers to uniquely identity a combination of values.


Non Flags example

Consider the following enum, used to indicate which destinations data should be published to:

enum PublishDestination : short
{
    None = 0,
    File = 1,
    Api = 2,
    Database = 4,
    Console = 8
};

Iterating through each possible combination of values as follows:

for (int pd = 0; pd < 16; pd++)
    Console.WriteLine("{0,3} - {1:G}", pd, (PublishDestination)pd);

Results in the following output:

0 - None
1 - File
2 - Api
3 - 3
4 - Database
5 - 5
6 - 6
7 - 7
8 - Console
9 - 9
10 - 10
11 - 11
12 - 12
13 - 13
14 - 14
15 - 15

As you can see, only the values represented in the enum (0, 1, 2, 4, 8) are converted. The runtime doesn't know, for instance, that 3 = 1 + 2 = File + Api

Introducing the Flags attributes indicates that the enum can be treated as a set of flags.


Flags example

Consider the same enum example from above, except now the Flags attribute has been introduced:

[Flags]
enum PublishDestination : short
{
    None = 0,
    File = 1,
    Api = 2,
    Database = 4,
    Console = 8
};

Iterating through each possible combination of values as follows:

for (int pd = 0; pd < 16; pd++)
    Console.WriteLine("{0,3} - {1:G}", pd, (PublishDestination)pd);

Now results in the following output:

0 - None
1 - File
2 - Api
3 - File, Api
4 - Database
5 - File, Database
6 - Api, Database
7 - File, Api, Database
8 - Console
9 - File, Console
10 - Api, Console
11 - File, Api, Console
12 - Database, Console
13 - File, Database, Console
14 - Api, Database, Console
15 - File, Api, Database, Console

All values are now accurately interpreted, either as a single enum value, or as a combination of enum values.


Notes

Adding the Flags attribute doesn't effect the behavior drastically, but it does make slight differences. With and without Flags the following behavior is the same:

  • A variable can still contain a combination of enum values
  • Enum.Parse operates the same in both cases
  • The HasFlag method on the enum operates the same in both cases
  • Bitwise operations behavior is the same in both cases

Adding the Flags attribute:

  • Changes the ToString() result
  • Indicates to readers of the code, that the enum is used as a flag and an enum variable could contain a combination of values

So while not drastic, it is best practice and a good idea to add the Flags attribute if the enum is intended to be used as flags.


References

FlagsAttribute Class

Daily Drop 79: 23-05-2022

At the start of 2022 I set myself the goal of learning one new coding related piece of knowledge a day.
It could be anything - some.NET / C# functionality I wasn't aware of, a design practice, a cool new coding technique, or just something I find interesting. It could be something I knew at one point but had forgotten, or something completely new, which I may or may never actually use.

The Daily Drop is a record of these pieces of knowledge - writing about and summarizing them helps re-enforce the information for myself, as well as potentially helps others learn something new as well.
c# .net enum attribute flags