ALLINSIGHT

Home of the AlmostImplementedException

Bit-Flags with enums

Today i want to show you how to use enumerations to set multiple values in a variable using bit-flags. Normaly enums are an easy way to set a single value and check later which value is set working with a static name throughout your entire application. Enums are much better then magic numbers or constants when you have multiple choices, but that will be dicussed in another post.

Bit-Flags are used for many many years and are a fast and light way to set multiple values in one variable. If you already know how to work with Bit-Flags and just interested in the Bit-Flag-Enum, skip the following part.

Bit-Flags
Before we start with the Bit-Flags we’ll have a look at the alternative. One or more boolean-variables. A boolean variable needs 1 Byte to store its value. Actually only one bit would do the job (0 = false and 1 = true), but the system can not use the other 7 bits for anything else. Imaging now we want the user to select 0, 1 or multiple values out of of a list with 8 different things. For our example we’ll use 8 pizza toppings:

– mozarella
– fresh tomatos
– sweetcorn
– onion
– chicken
– parma ham
– tuna
– pepperoni

Since we want to store multiple values we would need 8 booleans, which means 8 bytes are used to store these values. That doesn’t sound much, but when we use Bit-Flags it just would be one byte. If you have to store millions of these choices it would made a big difference.
But it also would be hard to handle all these booleans. It would be easier to use a List and put the used ingredients in there. In other examples this might not event be possible.

But back to the Bit-Flags. In order to use them, we need an easy way to manipulate and read a single bit.
Thats done with basic bit-operations every (good) programming language understand. We’ll use logical OR (in c# |) to set it, logical AND (in c# &) to check it and logical XOR (in c# ^) to remove it.
To demonstrate how it works, we first need to define which ingredient is represented by which bit. Bits are written from right to left and therefor mozarella gets the value 00000001, fresh tomatos 00000010, sweetcorn 00000100 and so on.

How to set a Bit-Flag => OR
Now we want to set onions and mozarella as ingredients and use OR to set them. A logical OR is comparing every bit of the two bytes and if it is 1 in one or both bytes then it is also 1 in the resulting byte. Otherwise it is 0.

fresh byte

00000000

OR

onion

00001000

OR

mozarella

00000001


Result

00001001

If we would use an OR with the result and onion again, nothing would change, because the 4th bit (from the right) is already set and the result of OR is always 1 if one or both are 1.

The C#-Code looks like this (the enum Ingredients will be definded later)

How to check a Bit-Flag => AND
To check if an ingredients is set we just use a logical AND which returns 1 if both checked bits are 1. If one or both are 0 then the result is 0. When we check if onions are set only one bit in both bytes are set. The 4th from the right. And only this one is set in the new result.

Result

00001001

AND

onion

00001000


new Result

00001000

Since we use an enum, this result is mapped to onions and WriteLine put Onions on the screen.

If we would check the result with parma ham no bits are set in both bytes so the result is 0, which is mapped to Nothing.
Which is an acutal value of the Ingredients-Enum with the value of 0 :-).

To check the value with an if-statement, you have to write it this way (a better way is described down at the enum)

How to unset a Bit-Flag => XOR
Now to the final thing, unset of an ingredient. To do that we wanted to use a logical XOR. With XOR the result is only 1 if both bits are different. If both are set or both are unset then the result is 0.
Since one of the bits is always set (the one from the enum), XOR acutally doesn’t unset the bit, it toggles. If the ingredient-bit is set, bot are 1 and the result 0. But if it is not, only one of the bits is set and the result is 1.
Only a XAND can truly remove an ingredient from the result, but c# (and most other programming languages) don’t know it.

When we use XOR with Onions on our result the following will happen:

Result

00001001

XOR

onion

00001000


new Result

00000001

And if we do it again we get the former result, again.

new Result

00000001

XOR

onion

00001000


new Result

00001001

This all could be done with any bit-value, but the title of this post said something about enum.

A Bit-Flag-Enum
In order to work with Enum-Values as bit-flags its just enough to set the proper values like descripted above. Its the same as if you were working with constants.
But if you want to get the resulting Bit-Flag-Map as Enum-Values you have to use the attribut [FlagsAttribute], which is defined in the System namespace. This attribut enables the enum to handle one number as multiple values.

Lets have a look at the resulting enum and then discuss it :-):

The Flags-Attribut tells the enum that a given value can consists of multiple flag-values. The enum now parses a given number and tells which values are set. The enum itself is defined as byte, because we don’t need larger numbers here.
Each value of the enum uses another bit. Thats very important, because if 2 values uses the same you wouldn’t know which one is mean. Thats why Sweetcorn uses 4, because 3 is in bit 00000011. The Enum would think you mean Mozarella AND FreshTomato.

The Nothing-Entry is for your convenience and should show how, not to use 0 as first value. Quite a few examples on the internet make this mistake, because of Microsofts example. The Example there uses colors and the first one (Black) is meant as “Nothing is choosed”, but not everybody got that.

On the part “How to check a Bit-Flag => AND” I showed a way to check which value is set. That way is very complicated and with .Net 4 there is a better solution. Have a look at this:

Thats quite simple and another good reason to use a Flag-Enum instead of multiple constants.
And here follows another one. Microsoft recommened to use short-cuts if you use 2 or more flag frequently together. In our case we’ll add a Tonno-Shortcut.
I define Tonno as Tuna + Onion + Mozarella and add this to the enum:

After that we’re a able to set Tonno and check all 3 ingredients separately. But also can we set all ingredients after another and if they match the Tonno-definishen, Tonno is also set.

Lets try another example and see how everything works together.

First I set 2 ingrediant Onions and Mozarella and the result is written on screen.
Then i add another ingredient (Tuna) and watch the result again.
And a fourth ingredient is added (fresh Tomatos).
Then we check if our result has Onions.
And finally we remove the Tuna.

The resulting screen output looks like this:

Mozarella, Onion
Tonno
FreshTomatos, Tonno
Yes, there are onions!
Mozarella, FreshTomatos, Onion

I hope this post is useful and comprehensible (yes, that one is for you Chris ;-))

Share :

, , ,

Leave a Reply

Your email address will not be published. Required fields are marked *