Flags, enum. In C#, Flags allow an enum value to contain many values. An enum type with the Flags attribute can have multiple constant values assigned to it.
With Flags, it is still possible to test enums in switches and if-statements. Flags can be removed or added. We can specify multiple flags with the "or" operator. The HasFlag() method is helpful.
First example. This program introduces a FileAttributes enum. We use the values 0, 1, 2, 4 to indicate the underlying bits for each value—we should double each value to avoid conflicts.
Part 1 We use the bitwise "OR" operator to set multiple values on an instance of the FileAttributes enum.
Part 5 We can test the enum value again to determine whether we correctly removed the flag from it.
using System;
class Program
{
[Flags]
enum FileAttributes
{
None = 0,
Cached = 1,
Current = 2,
Obsolete = 4,
}
static void Main()
{
// Part 1: create new enum instance with flags.
Console.WriteLine("SET CACHED AND CURRENT FLAGS");
var attributes = FileAttributes.Cached | FileAttributes.Current;
// Part 2: see if current flag is set.
if (attributes.HasFlag(FileAttributes.Current))
{
Console.WriteLine("File is current");
}
// Part 3: see if obsolete flag is not set.
if (!attributes.HasFlag(FileAttributes.Obsolete))
{
Console.WriteLine("File is not obsolete");
}
// Part 4: remove current flag.
Console.WriteLine("REMOVE CURRENT FLAG");
attributes &= ~FileAttributes.Current;
// Part 5: see if current flag is set again.
if (!attributes.HasFlag(FileAttributes.Current))
{
Console.WriteLine("File is not current");
}
}
}SET CACHED AND CURRENT FLAGS
File is current
File is not obsolete
REMOVE CURRENT FLAG
File is not current
Switch, Flags. This example shows an enum with 6 bit flags in it. Notice how the word [Flags] appears on top of the enum, with the square brackets.
Info The method Check shows how to switch on enum flags. We act on combinations of the flags in a constant-time expression.
Note The "|" operator is used in the cases. This means the values are combined.
Tip The values 0x0, 0x1, 0x2, 0x4 are powers of 2. Powers of 2 contain one bit set, moving from the first to the final bit.
Tip 2 You could use the decimal values, 0, 1, 2, 4, 8 instead. This might be clearer.
using System;
class Program
{
[Flags]
enum RenderType
{
None = 0x0,
DataUri = 0x1,
GZip = 0x2,
ContentPage = 0x4,
ViewPage = 0x8,
HomePage = 0x10 // Next two values could be 0x20, 0x40
}
static void Main()
{
// Set the first type.
RenderType type1 = RenderType.ContentPage;
// Set the second type if the condition matches.
if (true)
{
type1 |= RenderType.GZip;
}
// Check the enum flags.
Check(type1);
// Set a new enum in three statements.
RenderType type2 = RenderType.ViewPage;
type2 |= RenderType.DataUri;
type2 |= RenderType.GZip;
// See if the enum contains this flag.
if ((type2 & RenderType.DataUri) == RenderType.DataUri)
{
Console.WriteLine("True");
}
// See if the enum contains this flag.
if ((type2 & RenderType.ContentPage) == RenderType.ContentPage)
{
throw new Exception();
}
// Check the enum flags.
Check(type2);
}
static void Check(RenderType type)
{
// Switch on the flags.
switch (type)
{
case RenderType.ContentPage | RenderType.DataUri | RenderType.GZip:
{
Console.WriteLine("content, datauri, gzip");
break;
}
case RenderType.ContentPage | RenderType.GZip: // first match
{
Console.WriteLine("content, gzip");
break;
}
case RenderType.ContentPage:
{
Console.WriteLine("content");
break;
}
case RenderType.ViewPage | RenderType.DataUri | RenderType.GZip: // second match
{
Console.WriteLine("view, datauri, gzip");
break;
}
case RenderType.ViewPage | RenderType.GZip:
{
Console.WriteLine("view, gzip");
break;
}
case RenderType.ViewPage:
{
Console.WriteLine("view");
break;
}
case RenderType.HomePage | RenderType.DataUri | RenderType.GZip:
{
Console.WriteLine("home, datauri, gzip");
break;
}
case RenderType.HomePage | RenderType.GZip:
{
Console.WriteLine("home, gzip");
break;
}
case RenderType.HomePage:
{
Console.WriteLine("home");
break;
}
}
}
}content, gzip
True
view, datauri, gzip
Notes, operators. The "|=" operator actually adds a flag to the enum, so the enum now contains two flag bits. You can use "|=" to add bits, while "and" will test bits without setting them.
And Bitwise AND returns a value with 1 in the targeted bit if both values contain the bit.
Tip You can therefore AND two values together and test the result for the target bit.
Also Bitwise OR returns 1 in the bit if either value has it set. It can be used in switch, setting all bits in the cases.
Discussion. When you are using enum flags, you are concerned about performance. The switch compiles to a jump table which is faster than if-else chains.
Enum flags represent more complex constants and combinations. We used HasFlag() and bitwise flags with enums. We can assign, add, set, check, and switch on flags.
Dot Net Perls is a collection of tested code examples. Pages are continually updated to stay current, with code correctness a top priority.
Sam Allen is passionate about computer languages. In the past, his work has been recommended by Apple and Microsoft and he has studied computers at a selective university in the United States.
This page was last updated on Aug 2, 2024 (new example).