What does the [Flags] enum attribute mean in C#?
From time to time I see an enum like the following:
[Flags]
public enum Options
{
None = 0,
Option1 = 1,
Option2 = 2,
Option3 = 4,
Option4 = 8
}
I don’t understand what exactly the [Flags] attribute does. Can someone provide a good explanation or example?
The [Flags] attribute in C# indicates that an enumeration can be treated as a bit field, meaning multiple enum values can be combined into a single value using bitwise operations. This allows you to store and manipulate multiple options or states efficiently in a single variable, where each enum member represents a distinct bit position that can be either set or unset. Without this attribute, C# would treat the enum as a standard enumeration where only one value can be active at a time.
Contents
- What is the [Flags] Attribute?
- How Bitwise Operations Work with Flags
- Practical Examples of Using [Flags] Enums
- Best Practices for [Flags] Enums
- Common Use Cases for [Flags] Enums
What is the [Flags] Attribute?
The [Flags] attribute is a custom attribute in C# that you apply to enum declarations to indicate that the enum represents a set of flags rather than a single value. According to the Microsoft documentation, this attribute “indicates that an enumeration can be treated as a bit field; that is, a set of flags.”
When you apply the [Flags] attribute to an enum, you’re telling the compiler and runtime that:
- Multiple values from this enum can be combined
- Bitwise operations (AND, OR, XOR, NOT) are meaningful
- The enum should support methods like
HasFlag()for flag checking - The string representation should be more user-friendly when displaying combined values
Without the [Flags] attribute, combining enum values using bitwise operations would still work technically, but you wouldn’t get the semantic meaning, string formatting benefits, or IDE support that makes flags enums useful.
Key Insight: 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, as explained in the Stack Overflow discussion.
How Bitwise Operations Work with Flags
Bitwise operations are the foundation of how flags enums work. Each enum member in a flags enum should be assigned a value that is a power of two (1, 2, 4, 8, 16, etc.), which corresponds to setting a single bit in an integer value.
The four main bitwise operations used with flags enums are:
Bitwise AND (&)
The AND operation is used to check if specific flags are set. It returns true (non-zero) only if both operands have the bit set.
Options options = Options.Option1 | Options.Option3;
bool hasOption1 = (options & Options.Option1) != Options.None; // true
bool hasOption2 = (options & Options.Option2) != Options.None; // false
Bitwise OR (|)
The OR operation is used to combine or set multiple flags. It returns a value where any bit set in either operand is set in the result.
Options combined = Options.Option1 | Options.Option2 | Options.Option4;
Bitwise XOR (^)
The XOR operation is used to toggle flags. It sets bits that are set in one operand but not both.
Options options = Options.Option1 | Options.Option2;
options ^= Options.Option1; // Removes Option1, leaves Option2
Bitwise NOT (~)
The NOT operation inverts all bits. It’s commonly used to clear specific flags.
Options options = Options.Option1 | Options.Option2 | Options.Option3;
options &= ~Options.Option2; // Removes Option2
As Alan Zucconi explains, “If the first bit is one, it is a melee attack; if the second bit is one, it is a fire attack, if the third bit is one it is an ice attack, and so on. It is important to notice in order for this to work, labels have to be manually initialised as powers of two.”
Practical Examples of Using [Flags] Enums
Let’s explore some practical examples that demonstrate the power and flexibility of flags enums.
Example 1: File Permissions
[Flags]
public enum FilePermissions
{
None = 0,
Read = 1,
Write = 2,
Execute = 4,
Delete = 8
}
// Setting permissions
FilePermissions permissions = FilePermissions.Read | FilePermissions.Write;
// Checking permissions
if ((permissions & FilePermissions.Read) != FilePermissions.None)
{
Console.WriteLine("User can read the file");
}
if ((permissions & FilePermissions.Execute) == FilePermissions.None)
{
Console.WriteLine("User cannot execute the file");
}
// Adding permissions
permissions |= FilePermissions.Execute;
// Removing permissions
permissions &= ~FilePermissions.Write;
Example 2: UI Controls with Multiple States
[Flags]
public enum ControlState
{
None = 0,
Visible = 1,
Enabled = 2,
Focused = 4,
Selected = 8
}
// Control with multiple states
ControlState state = ControlState.Visible | ControlState.Enabled;
// Check if control is visible and enabled
bool isActive = (state & (ControlState.Visible | ControlState.Enabled)) != ControlState.None;
// Toggle focus state
state ^= ControlState.Focused;
Example 3: Burger Toppings (from Aaron Bos)
[Flags]
public enum BurgerToppings
{
None = 0,
Lettuce = 1,
Tomato = 2,
Onion = 4,
Pickle = 8,
Cheese = 16,
Bacon = 32
}
// Order with multiple toppings
BurgerToppings order = BurgerToppings.Lettuce | BurgerToppings.Tomato | BurgerToppings.Bacon;
// Check if order has cheese
bool hasCheese = order.HasFlag(BurgerToppings.Cheese); // false
As Aaron Bos demonstrates, “By adding the Flags attribute the enum will now be treated as a set of bit flags instead of a standard enum. If you’re unfamiliar with the concept of a bit flag, you can imagine each member representing one bit.”
Example 4: Modern C# with Binary Literals
C# 7.0 introduced binary literals, making flags enums even more readable:
[Flags]
public enum AttackType
{
None = 0b000000,
Melee = 0b000001,
Fire = 0b000010,
Ice = 0b000100,
Poison = 0b001000
}
// Combine attacks
AttackType attacks = AttackType.Melee | AttackType.Fire;
Best Practices for [Flags] Enums
When working with flags enums, following these best practices will help you avoid common pitfalls and create more maintainable code:
1. Use Powers of Two Values
Always assign enum values that are powers of two (1, 2, 4, 8, 16, 32, etc.). This ensures each value represents a single bit position.
[Flags]
public enum GoodExample
{
None = 0,
Option1 = 1, // 2^0
Option2 = 2, // 2^1
Option3 = 4, // 2^2
Option4 = 8 // 2^3
}
// Avoid this:
[Flags]
public enum BadExample
{
None = 0,
Option1 = 1,
Option2 = 2,
Option3 = 3, // Not a power of two!
Option4 = 4
}
2. Include a None Value
Always include a None value set to 0. This represents the absence of any flags and is useful for default values and comparisons.
3. Use Left Shift Operator for Readability
Instead of manually calculating powers of two, use the left shift operator (<<):
[Flags]
public enum Colors
{
None = 0,
Black = 1 << 0, // 1
Red = 1 << 1, // 2
Green = 1 << 2, // 4
Blue = 1 << 3 // 8
}
4. Consider the Data Type
Most enums default to int, which gives you 32 bits (31 usable flags for positive values). If you need more flags, consider using long:
[Flags]
public enum LongFlags : long
{
None = 0,
Flag1 = 1L << 0,
Flag2 = 1L << 1,
// ... up to 64 flags
}
However, as Alan Zucconi warns, “since enums are normally stored into Int32, it’s unwise to have an enum with more then 32 different labels.”
5. Use HasFlag() Method for Checking
The HasFlag() method provides a clean way to check if specific flags are set:
if (options.HasFlag(Options.Option1))
{
// Option1 is set
}
However, be aware that HasFlag() has some performance implications and may be slower than direct bitwise operations in performance-critical code.
6. Organize Enums Separately
As recommended by R. Mauro, “Consider placing enums in their own files for better organization.”
7. Provide a “All” or “Everything” Flag
For convenience, include a flag that combines all other flags:
[Flags]
public enum Options
{
None = 0,
Option1 = 1,
Option2 = 2,
Option3 = 4,
Option4 = 8,
All = Option1 | Option2 | Option3 | Option4
}
Common Use Cases for [Flags] Enums
Flags enums are particularly useful in several scenarios:
1. Permission Systems
As shown earlier, flags enums are perfect for representing user permissions, file access rights, or API scopes.
2. Configuration Options
When you have multiple configuration settings that can be combined:
[Flags]
public enum LogLevel
{
None = 0,
Error = 1,
Warning = 2,
Info = 4,
Debug = 8,
Trace = 16
}
// Set logging level
LogLevel logLevel = LogLevel.Error | LogLevel.Warning | LogLevel.Info;
3. Asset Properties or Tags
In game development or content management systems:
[Flags]
public enum AssetTags
{
None = 0,
Character = 1,
Environment = 2,
Animated = 4,
Interactive = 8,
Collectible = 16
}
4. Message Types or Protocol Flags
In networking or messaging systems:
[Flags]
public enum MessageType
{
None = 0,
Request = 1,
Response = 2,
Notification = 4,
Error = 8
}
5. UI State Management
For tracking the state of UI elements or components.
As The Burning Monk explains, “You use the FlagsAttribute attribute to create an enum type as bit flags which you can then interact with using the AND (&), OR (|), NOT (~) and XOR (^) bitwise operations.”
Conclusion
The [Flags] attribute transforms a standard C# enum into a powerful bit field that can represent multiple values simultaneously. Here are the key takeaways:
-
Purpose: The
[Flags]attribute indicates that an enum should be treated as a collection of flags rather than a single value, enabling bitwise operations. -
Implementation: Use powers of two (1, 2, 4, 8, 16…) for enum values to ensure each represents a distinct bit position.
-
Operations: Leverage bitwise AND (
&) for checking flags, OR (|) for combining flags, XOR (^) for toggling, and NOT (~) for clearing flags. -
Best Practices: Include a
Nonevalue (0), use left shift operators for readability, consider data type limitations, and organize enums thoughtfully. -
Use Cases: Flags enums excel in permission systems, configuration management, state tracking, and any scenario where you need to represent multiple binary states efficiently.
By mastering flags enums, you can write more efficient, readable, and maintainable C# code for scenarios that require handling multiple binary states or options. The combination of the [Flags] attribute with bitwise operations provides a clean and performant solution that’s been a cornerstone of C# development since the language’s inception.
Sources
- What does the [Flags] Enum Attribute mean in C#? - Stack Overflow
- System.FlagsAttribute class - .NET | Microsoft Learn
- FlagsAttribute Class (System) | Microsoft Learn
- Defining and Using Enums as Bit Flags in C# - Aaron Bos
- Enum, Flags and bitwise operators - Alan Zucconi
- C# - enum Flags Attribute Examples - Dot Net Perls
- Using enum types as bit flags in C# | theburningmonk.com
- What does the [Flags] Enum Attribute Mean? - net-informations.com
- C# Enum Bitwise Operations - R. Mauro
- Enum Flags in C# - DEV Community