Enum as flags
suggest changeThe FlagsAttribute
can be applied to an enum changing the behaviour of the ToString()
to match the nature of the enum:
[Flags]
enum MyEnum
{
//None = 0, can be used but not combined in bitwise operations
FlagA = 1,
FlagB = 2,
FlagC = 4,
FlagD = 8
//you must use powers of two or combinations of powers of two
//for bitwise operations to work
}
var twoFlags = MyEnum.FlagA | MyEnum.FlagB;
// This will enumerate all the flags in the variable: "FlagA, FlagB".
Console.WriteLine(twoFlags);
Because FlagsAttribute
relies on the enumeration constants to be powers of two (or their combinations) and enum values are ultimately numeric values, you are limited by the size of the underlying numeric type. The largest available numeric type that you can use is UInt64
, which allows you to specify 64 distinct (non-combined) flag enum constants. The enum
keyword defaults to the underlying type int
, which is Int32
. The compiler will allow the declaration of values wider than 32 bit. Those will wrap around without a warning and result in two or more enum members of the same value. Therefore, if an enum is meant to accomodate a bitset of more than 32 flags, you need to specify a bigger type explicitely:
public enum BigEnum : ulong
{
BigValue = 1 << 63
}
Although flags are often only a single bit, they can be combined into named “sets” for easier use.
[Flags]
enum FlagsEnum
{
None = 0,
Option1 = 1,
Option2 = 2,
Option3 = 4,
Default = Option1 | Option3,
All = Option1 | Option2 | Option3,
}
To avoid spelling out the decimal values of powers of two, the left-shift operator (<<) can also be used to declare the same enum
[Flags]
enum FlagsEnum
{
None = 0,
Option1 = 1 << 0,
Option2 = 1 << 1,
Option3 = 1 << 2,
Default = Option1 | Option3,
All = Option1 | Option2 | Option3,
}
Starting with C# 7.0, binary literals can be used too.
To check if the value of enum variable has a certain flag set, the HasFlag
method can be used. Let’s say we have
[Flags]
enum MyEnum
{
One = 1,
Two = 2,
Three = 4
}
And a value
var value = MyEnum.One | MyEnum.Two;
With HasFlag
we can check if any of the flags is set
if(value.HasFlag(MyEnum.One))
Console.WriteLine("Enum has One");
if(value.HasFlag(MyEnum.Two))
Console.WriteLine("Enum has Two");
if(value.HasFlag(MyEnum.Three))
Console.WriteLine("Enum has Three");
Also we can iterate through all values of enum to get all flags that are set
var type = typeof(MyEnum);
var names = Enum.GetNames(type);
foreach (var name in names)
{
var item = (MyEnum)Enum.Parse(type, name);
if (value.HasFlag(item))
Console.WriteLine("Enum has " + name);
}
Or
foreach(MyEnum flagToCheck in Enum.GetValues(typeof(MyEnum)))
{
if(value.HasFlag(flagToCheck))
{
Console.WriteLine("Enum has " + flagToCheck);
}
}
All three examples will print:
Enum has One
Enum has Two