DevCity.NET - http://devcity.net
eNumerous Options Using Enumerations
http://devcity.net/Articles/176/1/article.aspx
Fadzai Chamba
Fadz has been coding since 1993 when he was 13 years old when he first saw a computer that worked at St. Ignatius College in Harare Zimbabwe. His first programming experience was in GWBASIC. He thought he was learning the basics of computers and before long he was the renouned 'computer expert'. He later learned to use COBOL, Pascal, C, C++, PROLOG, Visual Basic, Java and Visual C++. Because of his first experiences he chose to ply his trade in Visual Basic. He came across .NET in July/August of 2003 and has been using it since. He has worked with VB(6) since October 2000, first as a Free lance developer, then for a company back to free lance. This yo-yo experience has continued to this day when he is now a Free Lance developer and starting a business in the Multi media field. He is a vbCity Guru who goes by the alias 'fabulous' and Spends a lot of his time inside .NET and the VB.NET and C# compilers. Fadz is also a DevCity .NETFella Award winner and constantly studies to improve his skills in .NET. 
by Fadzai Chamba
Published on 1/9/2006
 

eNumerous Options Using Enumerations

 

Introduction

For most of us, enumerations provide a means of selecting one of many options. What some of us don't know is that they also provide a means for us to specify more than one option at a time in one variable or argument.


Introduction

   For most of us, enumerations provide a means of selecting one of many options. What some of us don't know is that they also provide a means for us to specify more than one option at a time in one variable or argument. I came to this realization when I happened to visit a couple of students who were working on a college project in Visual Basic 6 recently. A part of their application allowed a user to select one or more of a set of eight options. To do this, they had 8 Boolean variables to determine which options were selected and I had to come in and point out to them that using an enumeration was the way to go.

 

First up, the Basics - Boolean algebra

  To start with, I will mention that this article presents Visual Basic .NET code, and not VB6 as the students had. I will take you on a quick recap of the basics of Boolean algebra. We will assume for the purposes of this article that True corresponds to 1 and False corresponds to 0, even though savvy VB programmers will argue that True equals -1.

  • The AND operation is a multiplication operation
  • The OR operation performs an addition
  • 0 AND 0 = 0
  • 1 AND 0 = 0
  • 1 AND 1 = 1
  • 0 OR 0 = 0
  • 1 OR 0 = 1
  • 1 OR 1 = 1

 

  That's as deep as I will go. We will accept these to be facts and debate them if we have to in another topic. These are the very basic rules for us to understand how to specify many options in one variable.

 

Flags

   Setting many options in one variable of an enumeration type is known as setting Flags. .NET provides us with the 'Flags' attribute for our enumerations. Applying the Flags attribute is as simple as placing <FLAGS()>in Visual Basic .NET and [Flags()] in C# before the enumerations declaration. For any of this to make sense, we will need a complete but simple example.

Our test application will have one enumeration called Stuff that will be used to determine which of 4 items a user has selected. The four items are Item1 through to Item4.

The enumeration is defined thus:
    <FLAGS()>Public Enum Stuff
        Item1 = 1
        Item2 = 2
        Item3 = 4
        Item4 = 8
    End Enum

Now, some of you may be wondering why I am counting in this odd way. Another small set of you will notice that I am counting in powers of 2. Going back to the old saying I heard before I knew what a computer was, "A computer only understands 1 and 0". This was someone's way of saying that a computer is a digital device, and works on binary data. The logic behind numbering the values this way will become apparent towards the end of the article.


 

 

Selecting One Item

Selecting One Item

   Selecting one item is no different from assigning a value the way you would do it in the normal way. Having declared a variable of type Stuff, all you need to do is assign the desired value. Here is a quick example:

Sub Main()
    Dim s As Stuff = Stuff.Item1

    DisplayStuff(s)
    Console.ReadLine()
End Sub

The following are the results you would get if you ran this code.

Item1 set : True
Item2 set : False
Item3 set : False
Item4 set : False

Selecting more than one item

   Having seen how to do it with one option selected, it follows that it is very simple to specify a second option. So if you wanted Item1 and Item3 together, this code looks logical:

Sub Main()
    Dim s As Stuff = Stuff.Item1
    s = Stuff.Item3

    DisplayStuff(s)
    Console.ReadLine()
End Sub

Running this code produces the following results:

Item1 set : False
Item2 set : False
Item3 set : True
Item4 set : False

What happened? It seems only Item3 is selected. To have more than one item selected, another strategy is needed. To solve this, go back to the section labeled Basics and read what it says under the Boolean algebra topic.


Bringing the basics forward

Having gone back to the basics, bring them back to where we are; that is, forward. When we want a second option enabled, what we are in essence doing is adding an option, or we are ORring an option. This is how we do it.

Sub Main()
    Dim s As Stuff = Stuff.Item1
    s = s Or Stuff.Item3

    DisplayStuff(s)
    Console.ReadLine()
End Sub

Running this code will show that both Item1 and Item3 are selected as expected. So, someone may be wondering why we had to use the OR operation.

 

Going Back To The Basics

Going back to the basics

The way we are reading the value of our enumeration is using a bitwise operation. Each value of the enumeration has a specific set of bits set, that is, a specific set of bits with the value of 1. For us to represent multiple values, we will need to do a little tap dancing around the bits so that we set alternating sets of bits for each option. This way, each option when set on its own will have one specific bit turned on.

This is the reason I numbered the values as powers of 2. For the purpose of simplifying our example, we will represent each value using 4 bits as follows:

<FLAGS()>Public Enum Stuff
    Item1 = 1       '0001
    Item2 = 2       '0010
    Item3 = 4       '0100
    Item4 = 8       '1000
End Enum

As you can see, setting both Item1 and Item3 will set two different bits to one. Using powers of 2 avoids having clashing values. Setting the first 3 items will have a value of 7 and this value can only be achieved by setting these three values. 7 in binary, as we all know, is represented this way:

0111

How do I read the values?

As I mentioned earlier, we read the values using a bitwise operator. In this case, the operator is AND.

To find out if the Item1 is selected, we would write code like this:

If CBool(s And Stuff.Item1) Then Console.WriteLine("Item1 is selected…")

It might be worth mentioning that the code can run without the CBool()  if you don't use Option Strict as I do. The code would, in that case, look like this:

If s And Stuff.Item1 Then Console.WriteLine("Item1 is selected…")

In any case, if the Item1 value had been selected, the corresponding message would be displayed to the console. I would recommend using CBool so that your code works whether or not someone is using Option Strict.

The DisplayStuff method uses a similar technique; here is all the code in it.

Console.WriteLine("Item1 set : {0}", CBool(s And Stuff.Item1))
Console.WriteLine("Item2 set : {0}", CBool(s And Stuff.Item2))
Console.WriteLine("Item3 set : {0}", CBool(s And Stuff.Item3))
Console.WriteLine("Item4 set : {0}", CBool(s And Stuff.Item4))

By dissecting the Item3 line, we can observe what's going on behind the scenes. As mentioned in the previous section, these values are set by turning some bits on, and some bits off.

     • When Item1 and Item3 are set, the value of s is equivalent to 0101 in binary.
     •   By using the operation (s And Item3), we are using the AND bitwise operation on the individual bits of the s variable, comparing it to the value of Item3 which is 0100.
    o This would result in the 0100. All the bits that don't correspond to a 1 in Item3's value are turned off, the 1 in this result is that way because the corresponding bit is 1.
   o This returns True because by using logic, anything that is not false is True. Since zero is false, anything that is not zero can be interpreted as True by the computer .

How do I turn a value off?

Supposing Item1 and Item3 are selected and the user then decided to turn Item1 off, the code needed to turn Item1 off without affecting anything else would use an AND operation rather than the usual OR. You would need to AND the current value with the complement of the item being deselected. What on earth is a complement? It is the result of a NOT operation, to put it quite simply. The code to turn Item1 off follows:

Dim s As Stuff = Stuff.All
    s = s And Not Stuff.Item1        'attempt to turn Item1 off

By doing that, the code is multiplying/ANDing the individual bits of the current value with the corresponding bits of the complement of Item1. The bit that is set to 1 in Item1 will now be zero and everything else is 1. This results in Item1's bit being turned off regardless of the previous value. Since everything else is ANDed by 1, everything else remains unchanged. As we all learned when starting mathematics, 1 multiplied by any value is whatever value we were multiplying with 1.

How does this work in real life?

Real life usage is not much different from what I presented here. In my current application I use this to keep track of user permissions. One variable manages 16 different restricted permission sets. The User class I have in my application has as many read-only properties and a method that is used to turn these permissions on or off. I trust that it won't be difficult to use these ideas in a real life project.

Conclusion

In this article, I discussed the role of enumerations marked as Flags for handling multiple options that can co-exist. This can be a useful technique and simplifies the management of multiple values. All these different values can be represented in a single variable and expansion (addition of new values) is very simple. By using this, you can come up with a large number of unnamed values by combining the different possible values. You will need to get familiar with the OR and AND bitwise operators. Feel free to comment or to contact me for further information.


Notes

1.    CBool is a function/operator in Visual Basic that converts an expression to Boolean. In C# or other languages, you can use Convert.ToBoolean() for the same purpose.

2.    If you download the project, you will see that I have used a conditional compilation variable to select between 2 sets of code, one that uses CBool, and one that doesn't. The values being represented as False are zero, and those being represented as True are equivalent to the value they are testing for, e.g. Item1 when testing for Item1. The code includes instructions on how to select the different versions.