Enum values as bit flags - using FlagsAttribute
The other day, I was using the RegexOptions enum when creating a Regular Expression, and I thought it would be useful to dedicate a blog entry to using enumeration values as flags.
The following is a poor example, but it should be illustrative enough.
Imagine we have a Client class, and one of the Client properties is ClientState. The ClientState enum can be defined as follows:
public enum ClientStates
{
Ordinary,
HasDiscount,
IsSupplier,
IsBlackListed,
IsOverdrawn
}
As you can see - these options could be combined in several ways. Rather then creating separate properties in the Client class, we could enable a bitwise combination of enumeration values by using the FlagsAttribute, when defining our enum type. See below.
[Flags]
public enum ClientStates
{
Ordinary,
HasDiscount,
IsSupplier,
IsBlackListed,
IsOverdrawn
}
This means we can now use the bitwise OR operator to combine these enum values. For instance:
Client c = new Client();
c.ClientState = (ClientStates.HasDiscount|ClientStates.IsSupplier|ClientStates.IsOverdrawn);
By setting the FlagsAttribute, the values for each enum value now effectively become bitflag patterns that look as follows if you see them in binary form:
00000000 0
00000001 1
00000010 2
00000100 4
00001000 16
00010000 32
00100000 64
01000000 128
As you can see, this bit pattern in our enum values enables us to use the bitwise operator and combine enum values. It is plain to see that all enum values combined, using the bitwise OR, would result in 11111111.
So, how do we check what particular ClientState values have been set? The key is the bitwise AND operator. Let's take our existing Client object 'c'.
[Flags]
public enum ClientStates
{
Ordinary, // 0000
HasDiscount, // 0001
IsSupplier, // 0010
IsBlackListed, // 0100
IsOverdrawn // 1000
}
So for instance, if we want to check c.ClientState for ClientStates.HasDiscount we can use the following expression:
(c.ClientState & ClientStates.HasDiscount) == ClientStates.HasDiscount
Assuming that c.ClientState contains HasDiscount, IsSupplier and IsOverdrawn, the bit patterns would look like:
c.ClientState: 1011
ClientStates.HasDiscount: 0001
(Logical AND): 0001
So by AND’ing the bit value to check for with the combined bit pattern, we either get the same enum bit pattern value back, or we get a bit pattern which only contains zero’s.
Here’s a little helper method you can use to check for particular ClientStates enum flag values:
public static bool ContainsClientState(ClientStates combined, ClientStates checkagainst)
{
return ((combined & checkagainst)==checkagainst);
}
That’s it for now. Feel free to leave any comments. Cheers!