What does the [Flags] enum attribute mean in C#?
From time to time I see enums 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 clear explanation with examples of how to use it effectively in C#?
The [Flags] attribute in C# indicates that an enumeration can be treated as a bit field, allowing it to represent multiple values simultaneously through bitwise operations. This attribute enables you to combine enum values using logical operators like OR (|), AND (&), and XOR (^), making it ideal for scenarios where you need to represent multiple options or settings in a single field. When properly implemented with powers of two values, the [Flags] attribute provides a memory-efficient and performant way to handle collections of related options.
Contents
- What is the [Flags] Attribute?
- How to Properly Define a Flags Enum
- Common Bitwise Operations with Flags
- Best Practices and Examples
- Parsing and Formatting Flags
- When to Use [Flags] vs Regular Enums
What is the [Flags] Attribute?
The [Flags] attribute is a custom attribute that tells the .NET runtime that an enumeration should be treated as a collection of bit flags rather than as a set of mutually exclusive values. According to the official Microsoft documentation, use the FlagsAttribute custom attribute for an enumeration only if a bitwise operation (AND, OR, EXCLUSIVE OR) is to be performed on a numeric value.
The key difference between a regular enum and a flags enum is that:
- Regular enum: Represents exactly one value from the set (like single-choice options)
- Flags enum: Can represent any combination of values from the set (like multiple-choice options)
For example, if you have a file permissions enum, a regular enum might force you to choose only “Read” or “Write”, but a flags enum allows you to have both “Read” and “Write” permissions simultaneously.
Key Insight: The
[Flags]attribute doesn’t change the underlying behavior of bitwise operations - it’s more about semantic clarity and enabling better debugging and string formatting capabilities.
How to Properly Define a Flags Enum
To create an effective flags enum, you must follow these critical rules:
1. Use Powers of Two Values
Each flag value must be a power of two (1, 2, 4, 8, 16, 32, etc.). This ensures that each flag occupies a unique bit position in the binary representation, preventing overlap.
[Flags]
public enum FilePermissions
{
None = 0, // 0000
Read = 1, // 0001
Write = 2, // 0010
Execute = 4 // 0100
}
2. Include a None Value
Always include a None = 0 value to represent the absence of any flags. This is particularly useful for initialization and comparison operations.
3. Consider Common Combinations
For frequently used flag combinations, create dedicated enum members. As Microsoft documentation suggests:
[Flags]
public enum FilePermissions
{
None = 0,
Read = 1, // 0001
Write = 2, // 0010
Execute = 4, // 0100
ReadWrite = Read | Write, // 0011
All = Read | Write | Execute // 0111
}
4. Use Binary Notation for Clarity
For better readability, especially with larger numbers, you can use binary notation:
[Flags]
public enum AdvancedOptions
{
None = 0b0000_0000,
FastProcessing = 0b0000_0001,
MemoryOptimized = 0b0000_0010,
ThreadSafe = 0b0000_0100,
DebugMode = 0b0000_1000
}
Common Bitwise Operations with Flags
Flags enums work with bitwise operations. Here are the most commonly used operations:
Setting Flags (OR Operation)
Use the bitwise OR operator (|) to combine multiple flags:
var permissions = FilePermissions.Read | FilePermissions.Write;
// Result: ReadWrite (3 in binary: 0011)
Checking Flags (AND Operation)
Use the bitwise AND operator (&) to check if specific flags are set:
if ((permissions & FilePermissions.Read) == FilePermissions.Read)
{
Console.WriteLine("Read permission is set");
}
// More concise way:
if (permissions.HasFlag(FilePermissions.Read))
{
Console.WriteLine("Read permission is set");
}
Removing Flags
Use the bitwise AND with the complement to remove flags:
// Remove Write permission
permissions = permissions & ~FilePermissions.Write;
Toggling Flags
Use the XOR operator (^) to toggle flags (add if not present, remove if present):
permissions = permissions ^ FilePermissions.Execute;
Checking Multiple Flags
To check if multiple flags are set:
if ((permissions & (FilePermissions.Read | FilePermissions.Write)) != 0)
{
Console.WriteLine("Either Read or Write permission is set");
}
Best Practices and Examples
Example 1: File Permissions
[Flags]
public enum FilePermissions
{
None = 0,
Read = 1,
Write = 2,
Execute = 4,
Delete = 8,
Full = Read | Write | Execute | Delete
}
// Usage
var userPermissions = FilePermissions.Read | FilePermissions.Write;
// Check permissions
if (userPermissions.HasFlag(FilePermissions.Read))
{
Console.WriteLine("User can read files");
}
// Add permission
userPermissions |= FilePermissions.Execute;
// Remove permission
userPermissions &= ~FilePermissions.Write;
Example 2: Days of the Week
[Flags]
public enum DaysOfWeek
{
None = 0,
Monday = 1,
Tuesday = 2,
Wednesday = 4,
Thursday = 8,
Friday = 16,
Saturday = 32,
Sunday = 64,
Weekdays = Monday | Tuesday | Wednesday | Thursday | Friday,
Weekend = Saturday | Sunday
}
// Usage
var workSchedule = DaysOfWeek.Monday | DaysOfWeek.Wednesday | DaysOfWeek.Friday;
// Check if working on weekend
if ((workSchedule & DaysOfWeek.Weekend) != 0)
{
Console.WriteLine("Working on weekend");
}
Example 3: User Preferences
[Flags]
public enum UserPreferences
{
None = 0,
DarkMode = 1,
AutoSave = 2,
Notifications = 4,
Analytics = 8,
HighContrast = 16
}
// Combining preferences
var preferences = UserPreferences.DarkMode | UserPreferences.AutoSave | UserPreferences.Notifications;
// Checking bit by bit
foreach (UserPreference preference in Enum.GetValues(typeof(UserPreference)))
{
if (preferences.HasFlag(preference))
{
Console.WriteLine($"Preference enabled: {preference}");
}
}
Performance Considerations
According to Dot Net Perls, when using enum flags, you should be concerned about performance. Bitwise operations are extremely fast, but be mindful of:
- Memory usage: Flags enums use the same memory as integer types
- Validation overhead: Always validate user input for flags enums
- String formatting: Flags enums have special string formatting behavior
Parsing and Formatting Flags
String Parsing
You can parse comma-separated strings into flags:
string permissionsString = "Read,Write";
FilePermissions permissions = (FilePermissions)Enum.Parse(typeof(FilePermissions), permissionsString);
String Formatting
Flags enums have special behavior when converted to strings:
FilePermissions permissions = FilePermissions.Read | FilePermissions.Write;
Console.WriteLine(permissions.ToString());
// Output: "Read, Write"
Custom Formatting
For better control over the string representation:
[Flags]
public enum FilePermissions
{
None = 0,
Read = 1,
Write = 2,
// ...
public override string ToString()
{
return this switch
{
Read => "Read-only",
Write => "Write-only",
Read | Write => "Read/Write",
Full => "Full access",
_ => base.ToString()
};
}
}
When to Use [Flags] vs Regular Enums
Use Regular Enums When:
- Only one value from the enum should be selected at a time
- The values represent mutually exclusive states or options
- You need string-to-enum conversion without bitwise operations
- The enum values don’t need to be combined
Use Flags Enums When:
- Multiple values can be selected simultaneously
- You need to represent combinations of options
- Memory efficiency is important (storing multiple booleans in one field)
- You’re working with system-level flags, permissions, or settings
Decision Flow
Do you need to represent multiple values at once?
├── Yes → Use [Flags] enum
│ └── Are values mutually exclusive?
│ └── Yes → Consider if flags are really needed
└── No → Use regular enum
Common Use Cases for Flags Enums:
- Permissions and Access Control: Read, Write, Execute permissions
- Configuration Settings: Various application options and preferences
- Error Codes: Multiple error conditions that can occur simultaneously
- Feature Flags: Enable/disable multiple features
- Days/Times: Days of the week, time periods
- File Attributes: Hidden, System, Archive, Read-only
Conclusion
The [Flags] attribute in C# is a powerful tool for representing multiple values in a single enumeration. When used correctly with powers of two values, it provides an efficient and clean way to handle collections of related options. Key takeaways include:
- Always use powers of two (1, 2, 4, 8, etc.) for flag values to ensure no overlap
- Include a None value (0) for clear initialization and comparison
- Use bitwise operators (
|,&,~,^) to manipulate flags - Consider common combinations as dedicated enum members for better readability
- Validate user input when working with flags to prevent invalid combinations
Flags enums are particularly useful for permissions, settings, and any scenario where you need to represent multiple boolean options efficiently. By following these best practices, you can create clean, maintainable code that takes full advantage of the power of bitwise operations.
Sources
- What does the [Flags] Enum Attribute mean in C#? - Stack Overflow
- System.FlagsAttribute class - .NET | Microsoft Learn
- FlagsAttribute Class (System) | Microsoft Learn
- C# - enum Flags Attribute Examples - Dot Net Perls
- Flags Attribute For Enum in C# - Code Maze
- Defining and Using Enums as Bit Flags in C# - Aaron Bos
- Enum Flags in C# - DEV Community
- C# Enum Flags Attribute - TheDeveloperBlog