TL;DR
- Use the
Flags
attribute on your enum type - Use bit values as the enum representation because it allows you to use bitwise operators
- Add up enums into a variable using the "|" operator
- Use the
HasFlags()
method to determine whether one or more bit fields are set in an enumeration value.
You must have worked on a feature that involves switching between multiple options, and if you are a C# developer, you know you could easily do that with the enum
type.
The enum
type is a built-in value type which is the short form of the Enumeration type. Microsoft describes the enum
as a type defined by a set of named constants of the underlying integral numeric type. This means that instead of having your options as numerical values, enums provide a way for you to use their representation.
A typical enum type is like this:
enum ColorTypicalEnum: int
{
None = 0,
Black = 1,
Red = 2,
Green = 4,
Blue = 8
}
The int
type in front of the type tells the compiler the numerical type you want your enum
represented as.
Flags in enum
is an attribute that indicates that an enum type can be treated as a bit field. These bit fields are now grouped in a set of flags.
Here, you can represent the int in form of the enum fields as a bit. This makes working with the enum easier than the typical type.
[Flag]
enum ColorWithFlag: int
{
None = 0,
Black = 1,
Red = 2,
Green = 4,
Blue = 8,
... //after some really, really long color listing
ThisColorIsSoRare = 268435456
}
The bit values here would be hard to comprehend and even easier to get wrong, e.g., how is ThisColorIsSoRare = 268435456
? Good question, that is why you use bitwise operations instead.
So, we use the left shift operator:
[Flag]
enum ColorWithFlag: int
{
None = 0,
Black = 1,
Red = 1 << 1, //2
Green = 1 << 2, //4
Blue = 1 << 3, //8
...
ThisColorIsSoRare = 1 << 60, //268435456
AllColors = int32.MaxValue
}
Now, to the most interesting part of using flags. Because the Flag
attribute allows you to use bitwise operations, you can easily do cool stuff like this:
// group all the primary colors (i.e. red, blue, and green) into one variable
var primaryColors = ColorWithFlag.Red | ColorWithFlag.Green |
ColorWithFlag.Blue
//this sums the integer representation of the color in the `primaryColors` variable, so if you do
var primaryColorsIntegerValue = (int)primaryColors;
//you would get 14
You can check if a color exists in the primary color variable using the HasFlag
(which inner workings is a bitwise operation) method.
var isPrimaryColor = primaryColors.HasFlag(ColorWithFlag.Black);
//this returns false
There is a massive chance you use Enums in your present or next project, so you be ready to use this knowledge of flags. It will make your code cleaner.
Please do check the provided links for a better understanding and examples.
Top comments (5)
Nice article about the usage of flags!
I may be wrong but I think that an enum is considered as an integer by default and that the type is inferred and therefore you do not need to explicitly indicate it:
I also covered part of the subject a couple of days ago, if you want to check it out!
Smarter conditions with flags and enums
Pierre Bouillon for SFEIR ・ Jun 27 ・ 3 min read
Nice spot, Pierre. You are right.
I indicated the integer values because I wanted to make readers see what the values would be when they are changed to bit values.
I believe the Flag attribute just formats toString differently. Bitwise operators can be used on all Enums.
Loved this. I may have missed this somewhere but can you now store a value in an object that represents multiple enum values that isn't a list?
thank you, Stephen. If I understand your question well enough,
The only value you can store in (or update) an object that represents (multiple) enum value(s) without an explicit conversion is an enum.
Something like this:
And if you do an explicit cast,