BitFlags in C#
Awhile back I had a discussion about user permissions with a client. Specifically how to store the permissions in the database. As a software developer I wanted my object model to have explicit control over the security model. If you wanted to alter a person’s security you’d need to do so via a utility program or perhaps an administrative panel within the software.
The client wanted to be able to alter a field within a table in the database to change permissions. He thought it was much more efficient to have a DBA hop into the database and change a field. He further thought have a bunch of fields Boolean fields like “Read”, “Write”, “Publish”, “Edit”, and “Delete” were too cumbersome. He wanted to have a bit string where each bit represented a yes/no relationship with a type of permission.
This is something that can be represented beautiful with a special type of enum. Adding the [Flags] attribute to an enum turns it into a bit string just like above. It is implemented as follows.
1 2 3 4 5 6 7 8 9 | [Flags] public enum Permissions { None = 0 Read = 0x0001, Write = 0x0002, ReadWrite = Permissions.Read | Permissions.Write, Execute = 0x0004, Delete = 0x0005 } |
As you can see it looks as though it is a simple enum but isn’t quite that. You are allowed to combine enum values to create other values.
What is especially great is that
1 2 3 4 | Permissions permissions = Permissions.Read | Permissions.Execute; User user = new User("robber.baron", permissions); Console.Writeline(user.permissions.ToString()); |
The output of the final line is very user friendly. The output is:
Read, Execute
This is a native part of the common language runtime and is part of the .Net base library. This is a fantastic and simple language feature that provides a simple and intuitive way of dealing with the concept of bit strings without custom code.
I’ll never worry about having to implement a bit string again. In fact I might start using them more often.
Maybe I’m missing the way C# handles it, but it certainly looks to me like your code would treat (Read | Execute) the same as Delete ( (0×4 | 0×1) = 0×5 ). Normally bitflags are powers of 2 to avoid such a thing.
Dave,
You are right. I was just sloppily throwing together an example. Yes, normally they are powers of two so that each bit represents an “allowed/denied” pair. Thus you can have all sorts of combinations without confusion. Good catch.
Hello from Russia!
Can I quote a post in your blog with the link to you?
Of course you can. While I am mainly blogging this information for my own purposes, I am happy to share with whoever would want it.