Mastering the [Flags] Attribute in C#: Creating Powerful Bitwise Enums


When working with enums in C#, we usually think of them as a list of distinct values. However, there are situations where a variable should represent a combination of multiple enum values at the same time — for example, user permissions, file access modes, or UI display options.
That’s where the [Flags]
attribute comes in.
What is [Flags]
in C#?
The [Flags]
attribute is applied to an enum to indicate that it should be treated as a bit field — a set of flags that can be combined using bitwise operations.
A regular enum variable can only hold one value at a time, but a [Flags]
enum can store multiple active values in a single variable.
Defining a [Flags]
Enum
When defining a flags enum, each value should be a power of 2:
[Flags]
public enum FileAccess
{
None = 0,
Read = 1, // 0001
Write = 2, // 0010
Execute = 4, // 0100
ReadWrite = Read | Write, // 0011
All = Read | Write | Execute // 0111
}
Combining Flags
You can combine multiple flags using the bitwise OR (|
) operator:
FileAccess access = FileAccess.Read | FileAccess.Write;
Console.WriteLine(access);
// Output: Read, Write
Checking for a Flag
To see if a flag is set, use the bitwise AND (&
) operator:
bool canRead = (access & FileAccess.Read) == FileAccess.Read; // true
bool canExec = (access & FileAccess.Execute) == FileAccess.Execute; // false
Why Use [Flags]
Instead of a Regular Enum?
Without [Flags]
, the combination logic still works, but the ToString()
output will show the raw number instead of meaningful flag names:
Console.WriteLine(access);
// Without [Flags]: 3
// With [Flags]: Read, Write
Real-World Example: User Permissions
A common use case for [Flags]
is managing user permissions in an application.
[Flags]
public enum UserPermissions
{
None = 0,
ViewDashboard = 1,
EditUsers = 2,
ManageProducts = 4,
AccessReports = 8,
All = ViewDashboard | EditUsers | ManageProducts | AccessReports
}
Assigning Permissions:
UserPermissions admin = UserPermissions.ViewDashboard | UserPermissions.EditUsers | UserPermissions.AccessReports;
Console.WriteLine(admin);
// Output: ViewDashboard, EditUsers, AccessReports
Checking Permissions:
bool canEdit = (admin & UserPermissions.EditUsers) == UserPermissions.EditUsers; // true
bool canManageProducts = (admin & UserPermissions.ManageProducts) == UserPermissions.ManageProducts; // false
Filtering Users by Permission:
var users = new List<(string Name, UserPermissions Permissions)>
{
("Ali", UserPermissions.ViewDashboard | UserPermissions.AccessReports),
("Sara", UserPermissions.ViewDashboard | UserPermissions.EditUsers),
("Reza", UserPermissions.All)
};
var reportUsers = users.Where(u => (u.Permissions & UserPermissions.AccessReports) == UserPermissions.AccessReports);
foreach (var user in reportUsers)
{
Console.WriteLine(user.Name); // Ali, Reza
}
Best Practices for [Flags]
Use powers of 2 for each flag (1, 2, 4, 8, 16…).
Define a
None = 0
value.Avoid overlapping bit values.
Use
[Flags]
only when multiple values may be combined.
Conclusion
The [Flags]
attribute in C# is a powerful tool for representing multiple options in a single variable. It improves readability, saves storage, and makes your code cleaner when dealing with combinations of states or permissions.
💡 Pro Tip: You can store [Flags]
enums directly in a database as integers, making them both efficient and easy to query.
I’m Morteza Jangjoo and “Explaining things I wish someone had explained to me”
#dotnet #csharp #enums #flags #programmingtips
Subscribe to my newsletter
Read articles from Morteza Jangjoo directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
