In today’s post, I’m going to talk about a feature in C# that, honestly, I had completely forgotten about. I first saw it at my very first job back in 2014/2015 and hadn’t come across it again until a couple of weeks ago.
At that moment, it sparked my interest and I thought, why not write a post about Flags in C#?
1 - What is the flag attribute in C# and what is it for?
Well, the flag
attribute is an attribute that you add to an enum to turn it into a bitwise enum. This means that each value represents a bit value.
In other words, when you use this attribute on an enum, it gets translated to binary values:
[Flags]
public enum TestFlags
{
FirstValue = 00,
SecondValue = 01,
ThirdValue = 10
}
In this example, the values are equivalent to:
FirstValue = 00000,
SecondValue = 00001,
ThirdValue = 00010
Note: technically, you can use binary literals like 0b0000
, but in the end it’s the same thing.
Or as a numeric value:
FirstValue = 0,
SecondValue = 1,
ThirdValue = 2
And of course, seeing this, you might ask yourself, what is it really for, or what is the practical use of the flag attribute?
2 - Real-world use case for the Flag attribute in C#
The easiest way to see how it works is with a real-world example, which is the specific case where I saw flags being used about 8 years ago: user permissions. Let’s say we have these permissions for a certain functionality:
- None
- View
- Create
- Edit
- Delete
We have a website with different actions. Technically, you don’t need to include “none”, but for clarity during the explanation, in my opinion, it makes things easier to follow.
We’re going to put these actions into our enum and assign them a value. As we’ve seen before, we can do this using integer values:
[Flags]
public enum Permissions
{
//None = 0, //0b0000
View = 1, //0b0001
Create = 2, //0b0010
Edit = 4, //0b0100
Delete = 8 //0b1000
}
We’re used to enums in C# only having one value assigned. If we stick with this example and have edit permissions assigned 4, does this mean we can also create and view?
Well, if we use an if statement like if(user.permissions == Permissions.Create)
it will fail, because we have a 4 there.
One way to fix this would be to check for greater than and less than, but then someone who can delete would also be able to create and edit, and maybe your logic doesn’t expect that.
This is where the real usefulness of the flag attribute comes in.
We’re working with binary here, so we have bits that tell us whether something is enabled or not. For example, if we can view, edit, and create, we have the first three options combined for a total of 7, and 7 in binary is 0b0111
. As you can see, those are the individual bits for each option, and they don’t conflict with each other.
If, for example, we can view and delete, but not edit or create, we’d have 0b1001
which is 9.
Now that we get that, we only need to know how to assign the values, which we do with the bitwise operator:
Permissions userPermissions = Permissions.View | Permissions.Delete;
And then we compare using the .HasFlag(...)
method:
if (userPermissions.HasFlag(Permissions.View))
{
//Then we can see the page;
}
if (userPermissions.HasFlag(Permissions.Create))
{
//then the user can see the create button
}
And as you can see, it works perfectly. In my opinion, it’s one of the best (if not the best) ways to handle permissions, because it lets you include a huge variety of combined permissions in a very simple way.
Before we finish, if you use .ToString()
on it, it will return the active flags as a comma-separated string. If you cast to int
, it gives you the numeric value. When reading from the database, you need to know how you stored it so you can map it back.
If there is any problem you can add a comment bellow or contact me in the website's contact form