Question
In C#, I sometimes see an enum declared like this:
[Flags]
public enum Options
{
None = 0,
Option1 = 1,
Option2 = 2,
Option3 = 4,
Option4 = 8
}
What exactly does the [Flags] attribute do?
I would like a clear explanation of what it means, when it should be used, and a practical example of how values from this enum can be combined and checked.
Short Answer
By the end of this page, you will understand what the [Flags] attribute means in C#, why flag enums use powers of two, how to combine enum values with bitwise operators, and how to test whether a specific option is present.
Concept
[Flags] is a special attribute in C# used on an enum to show that its values are intended to be combined as bit flags.
A normal enum usually represents one choice from many. For example, a DayOfWeek value is usually just one day at a time.
A flags enum represents multiple on/off options at the same time. Each enum value uses a different bit in the underlying number, so values can be combined into one variable.
For example:
[Flags]
public enum Options
{
None = 0,
Option1 = 1,
Option2 = 2,
Option3 = 4,
Option4 = 8
}
These values are powers of two:
1->00012->00104->01008->1000
Because each option uses a different bit, they can be combined without overlapping.
For example:
Options selected = Options.Option1 | Options.Option3;
This creates:
0001 | 0100 = 0101
So selected now means: Option1 and Option3 are both enabled.
What [Flags] actually does
The attribute does not magically change how bitwise operators work. You can still combine enum values without it.
What [Flags] mainly does is:
- communicates developer intent: this enum is meant to be combined
- improves formatting when converting enum values to strings
- helps tools and APIs treat the enum as a set of flags
For example, with [Flags], this:
Options selected = Options.Option1 | Options.Option3;
Console.WriteLine(selected);
prints:
Option1, Option3
Without [Flags], the output would often be the numeric value instead, such as:
5
Why it matters
Flags enums are common in real programs because they store many boolean settings in one value. They are useful when you want compact, fast, and expressive combinations such as:
- file permissions
- feature toggles
- display options
- user roles
- state tracking
The important rule is that each flag should have a unique bit, which usually means using powers of two.
Mental Model
Think of a flags enum like a row of light switches.
- Each switch is either off or on.
- Each enum value controls one switch.
- A single number stores the state of all switches together.
For example:
Option1= first switchOption2= second switchOption3= third switchOption4= fourth switch
If you turn on switch 1 and switch 3, the combined value remembers both.
So a normal enum is like choosing one item from a menu, while a [Flags] enum is like checking multiple boxes in a form.
Syntax and Examples
Basic syntax
[Flags]
public enum Options
{
None = 0,
Option1 = 1,
Option2 = 2,
Option3 = 4,
Option4 = 8
}
Combining flags
Use the bitwise OR operator | to combine values:
Options selected = Options.Option1 | Options.Option3;
Console.WriteLine(selected); // Option1, Option3
Checking for a flag
You can check whether a flag is set using &:
bool hasOption1 = (selected & Options.Option1) == Options.Option1;
bool hasOption2 = (selected & Options.Option2) == Options.Option2;
Console.WriteLine(hasOption1); // True
Console.WriteLine(hasOption2); // False
Adding a flag
selected |= Options.Option2;
Console.WriteLine(selected); // Option1, Option2, Option3
Removing a flag
selected &= ~Options.Option1;
Console.WriteLine(selected); // Option2, Option3
Using HasFlag
C# also provides a built-in method:
bool hasOption3 = selected.HasFlag(Options.Option3);
This is readable, though many developers prefer bitwise checks in performance-sensitive code.
A realistic example
[Flags]
public enum FilePermissions
{
None = 0,
Read = 1,
Write = 2,
Execute = 4
}
FilePermissions permissions = FilePermissions.Read | FilePermissions.Write;
Console.WriteLine(permissions); // Read, Write
Console.WriteLine((permissions & FilePermissions.Write) == FilePermissions.Write); // True
Console.WriteLine((permissions & FilePermissions.Execute) == FilePermissions.Execute); // False
This is a common pattern for representing multiple permissions in one value.
Step by Step Execution
Consider this example:
[Flags]
public enum Options
{
None = 0,
Option1 = 1,
Option2 = 2,
Option3 = 4,
Option4 = 8
}
Options selected = Options.Option1 | Options.Option3;
Step 1: Look at the binary values
Option1 = 1->0001Option3 = 4->0100
Step 2: Combine them with |
0001
0100
---- |
0101
The result is 0101, which is decimal 5.
So this line:
Options selected = Options.Option1 | Options.Option3;
stores the numeric value 5, but because this is a flags enum, that 5 represents:
Option1Option3
Step 3: Check whether Option1 is present
(selected & Options.Option1) == Options.Option1
Binary:
selected = 0101
Option1 = 0001
---------------- &
result = 0001
Since the result equals Option1, the flag is present.
Step 4: Check whether Option2 is present
(selected & Options.Option2) == Options.Option2
Binary:
selected = 0101
Option2 = 0010
---------------- &
result = 0000
Since the result is not equal to Option2, that flag is not present.
Step 5: Add another option
selected |= Options.Option2;
Binary:
0101
0010
---- |
0111
Now selected contains Option1, Option2, and Option3.
Step 6: Remove a flag
selected &= ~Options.Option1;
This clears the bit for Option1 and keeps the others.
Real World Use Cases
Flags enums are useful whenever several independent choices can be turned on at once.
Common examples
- File permissions: read, write, execute
- UI display options: show header, show footer, enable dark mode
- User roles or capabilities: can edit, can delete, can publish
- Search filters: include archived, include hidden, exact match only
- Logging options: log to console, file, database
- Game character states: poisoned, invisible, shielded
Example: notification channels
[Flags]
public enum NotificationChannels
{
None = 0,
Email = 1,
Sms = 2,
Push = 4
}
NotificationChannels channels = NotificationChannels.Email | NotificationChannels.Push;
This lets an application store multiple enabled notification methods in one value.
Example: API options
An API might accept a flags enum to let the caller request several options at once:
[Flags]
public enum LoadOptions
{
None = 0,
IncludeComments = 1,
IncludeHistory = 2,
IncludeAttachments = 4
}
Then the caller can write:
LoadOptions options = LoadOptions.IncludeComments | LoadOptions.IncludeAttachments;
Real Codebase Usage
In real projects, developers use flags enums to keep option handling clean and compact.
Common patterns
Guard clauses
Check whether a required flag exists before continuing:
if ((permissions & FilePermissions.Read) != FilePermissions.Read)
{
throw new InvalidOperationException("Read permission is required.");
}
Default value with None
Most flags enums define:
None = 0
This gives a clear empty state.
Combined named values
Developers often define reusable combinations:
[Flags]
public enum FilePermissions
{
None = 0,
Read = 1,
Write = 2,
Execute = 4,
ReadWrite = Read | Write
}
This improves readability and reduces repeated combinations.
Validation
Sometimes code checks whether a value contains only valid flags:
FilePermissions validFlags = FilePermissions.Read | FilePermissions.Write | FilePermissions.Execute;
bool isValid = (permissions & ~validFlags) == 0;
This is useful when values come from config files, APIs, or databases.
Configuration and options objects
Instead of many separate booleans like:
bool includeComments;
bool includeHistory;
bool includeAttachments;
a single flags enum can simplify a method signature:
LoadOptions options
This keeps APIs easier to extend later.
Common Mistakes
1. Using numbers that are not unique bits
Flags should usually be powers of two.
Broken
[Flags]
public enum BadOptions
{
None = 0,
Option1 = 1,
Option2 = 2,
Option3 = 3
}
3 is 0011, which overlaps with 1 and 2. That means Option3 is not an independent flag.
Better
[Flags]
public enum GoodOptions
{
None = 0,
Option1 = 1,
Option2 = 2,
Option3 = 4
}
2. Forgetting None = 0
Without a zero value, the enum has no clear “nothing selected” state.
Better pattern
None = 0
3. Thinking [Flags] does the combining
[Flags] does not combine values by itself. You still need bitwise operators such as | and &.
4. Using + instead of |
Sometimes beginners write:
var selected = Options.Option1 + Options.Option2;
This may appear to work for simple powers-of-two values, but it is not the correct operator for combining flags.
Correct
var selected = Options.Option1 | Options.Option2;
5. Comparing directly to one flag when multiple flags exist
Broken
if (selected == Options.Option1)
{
// This only works if Option1 is the only selected value
}
Better
if ((selected & Options.Option1) == Options.Option1)
{
// Option1 is present, even if others are also set
}
6. Using flags for mutually exclusive choices
Flags are for combinations. If only one value should ever be selected, a normal enum is better.
For example, Color.Red, Color.Green, and Color.Blue are usually not flags unless combinations are intended.
Comparisons
Flags enum vs normal enum
| Concept | Normal enum | [Flags] enum |
|---|---|---|
| Purpose | One choice from many | Multiple options combined |
| Values | Often sequential (0, 1, 2, 3) | Powers of two (1, 2, 4, 8) |
| Combination | Usually not combined | Combined with ` |
| Checking values | Direct comparison | Bitwise check with & |
| Example | DayOfWeek.Monday | `Read |
HasFlag vs bitwise &
| Approach | Example | Notes |
|---|---|---|
HasFlag | value.HasFlag(Options.Option1) | Easy to read |
Bitwise & | (value & Options.Option1) == Options.Option1 | Common and explicit |
Sequential values vs powers of two
| Enum values | Good for flags? | Why |
|---|---|---|
0, 1, 2, 3, 4 | No | Values overlap in binary |
0, 1, 2, 4, 8 | Yes | Each value uses a separate bit |
| vs &
| Operator | Use | Example |
|---|---|---|
| ` | ` | Combine flags |
& | Check common bits | (value & Read) == Read |
~ | Invert bits, often for removing | value &= ~Read |
Cheat Sheet
[Flags]
public enum MyFlags
{
None = 0,
A = 1,
B = 2,
C = 4,
D = 8
}
Rules
- Use
[Flags]when enum values can be combined. - Use
None = 0for the empty state. - Give each flag a unique bit:
1, 2, 4, 8, 16... - Combine flags with
|. - Check flags with
&orHasFlag. - Remove flags with
&= ~flag. - Use a normal enum if only one value should be chosen.
Common operations
Combine
var value = MyFlags.A | MyFlags.C;
Check
bool hasA = (value & MyFlags.A) == MyFlags.A;
bool hasA2 = value.HasFlag(MyFlags.A);
Add
value |= MyFlags.B;
Remove
value &= ~MyFlags.A;
Empty state
value = MyFlags.None;
Edge cases
- Avoid values like
3,5,6as individual flags unless they are intentional combinations. [Flags]improves readability and string formatting, but bitwise logic works even without it.selected == MyFlags.Aonly means A and nothing else.
FAQ
What does [Flags] do in C#?
It marks an enum as a set of bit flags, meaning multiple values are intended to be combined in one variable.
Do I need [Flags] to use bitwise operators on an enum?
No. Bitwise operators still work without it. [Flags] mainly improves readability, intent, and string formatting.
Why do flag enums use powers of two?
Because each value needs its own binary bit. That allows multiple values to be combined without overlapping.
Why is None = 0 commonly used?
It represents the empty state where no flags are set, which is useful as a default value.
How do I check if a flag is set?
Use either:
(value & MyFlags.A) == MyFlags.A
or:
value.HasFlag(MyFlags.A)
Can I use + to combine flags?
You should use | instead. + is not the correct operator for expressing flag combination.
When should I not use [Flags]?
Do not use it when the enum should represent only one choice at a time, such as a status or category.
Can a flags enum include combined named values?
Yes. For example:
ReadWrite = Read | Write
This is a common and useful pattern.
Mini Project
Description
Build a small permission system for a document editor. The editor should support separate permissions such as reading, writing, deleting, and sharing. This project demonstrates how a [Flags] enum can store multiple permissions in one value and how to add, remove, and check permissions in code.
Goal
Create a C# program that combines permission flags, checks access, and updates permissions safely.
Requirements
- Define a
[Flags]enum namedDocumentPermissionwithNone,Read,Write,Delete, andShare. - Create a variable representing a user's current permissions.
- Combine at least two permissions into one value.
- Check whether specific permissions are enabled.
- Add one permission and remove one permission.
- Print the permission set after each change.
Keep learning
Related questions
AddTransient vs AddScoped vs AddSingleton in ASP.NET Core Dependency Injection
Learn the differences between AddTransient, AddScoped, and AddSingleton in ASP.NET Core DI with examples and practical usage.
Best Way to Repeat a Character in C#: Building Repeated Strings Efficiently
Learn the best way to repeat a character in C#, compare StringBuilder, string concatenation, and simpler built-in options.
C# Access Modifiers and static: public, private, protected, and Defaults
Learn how C# public, private, protected, and default access control visibility, and how static differs from instance members.