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.
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);
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:
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:
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;
isValid = (permissions & ~validFlags) == ;
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 does the combining
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 &
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);
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]?
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.
C# Type Checking Explained: typeof vs GetType() vs is
Learn when to use typeof, GetType(), and is in C#. Understand exact type checks, inheritance, and safe type testing clearly.
C# Version Numbers Explained: C# vs .NET Framework and Why “C# 3.5” Is Incorrect
Learn the correct C# version numbers, how they map to .NET releases, and why terms like C# 3.5 are inaccurate and confusing.