DEV Community

Cover image for Mastering the `[Flags]` Attribute in C#: Creating Powerful Bitwise Enums
Morteza Jangjoo
Morteza Jangjoo

Posted on

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, sometimes we need a variable to represent a combination of multiple 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 } 
Enter fullscreen mode Exit fullscreen mode

Combining Flags

You can combine multiple flags using the bitwise OR (|) operator:

FileAccess access = FileAccess.Read | FileAccess.Write; Console.WriteLine(access); // Output: Read, Write 
Enter fullscreen mode Exit fullscreen mode

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 
Enter fullscreen mode Exit fullscreen mode

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 
Enter fullscreen mode Exit fullscreen mode

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 } 
Enter fullscreen mode Exit fullscreen mode

Assigning Permissions

UserPermissions admin = UserPermissions.ViewDashboard | UserPermissions.EditUsers | UserPermissions.AccessReports; Console.WriteLine(admin); // Output: ViewDashboard, EditUsers, AccessReports 
Enter fullscreen mode Exit fullscreen mode

Checking Permissions

bool canEdit = (admin & UserPermissions.EditUsers) == UserPermissions.EditUsers; // true bool canManageProducts = (admin & UserPermissions.ManageProducts) == UserPermissions.ManageProducts; // false 
Enter fullscreen mode Exit fullscreen mode

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 } 
Enter fullscreen mode Exit fullscreen mode

Best Practices for [Flags]

Use powers of 2 for each flag (1, 2, 4, 8, 16…).
Always 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.

#dotnet #csharp #enums #flags

I’m Morteza Jangjoo and “Explaining things I wish someone had explained to me”

Top comments (0)