Author avatar

Dániel Szabó

Enum Manipulation

Dániel Szabó

  • Aug 6, 2019
  • 7 Min read
  • 47 Views
  • Aug 6, 2019
  • 7 Min read
  • 47 Views
Languages Frameworks and Tools
C#

Introduction

For programmers coming from different languages, the enum is not a new concept. If we put it simply, enum is just a list of integer values represented by friendly names. That’s it. These are similar structures but only integers can be stored in enum values. After you learn about enums, we will move to explaining the debug process. As every code's development cycle contains a portion of time spent testing/debugging/fixing code from semantic errors. Sometimes you find logic errors which need to be fixed, no code is perfect for the first try; although, everyone tries to achieve that. Bugs are not something someone needs to be shy about, they happen. Although, it's better to catch them before they hit production.

Without Enums

Let's suppose you would like to use enum to describe the Tiers of your servers. The Tier is a logical bucket which highlights the importance of your servers starting from zero, which is the least important, and three, which is the most important.

1
2
3
4
public int None = 0;
public int Development = 1;
public int Testing = 2;
public int Production = 3;
csharp

This could, in turn, be used to assign the priority when you instantiate the server class. Let’s say our server class looks something like the following. We name the server and give it a priority. What happens if we want to promote the server from Development to Testing tier because the machine was moved from one room to the other due to capacity management reasons? It would be unwise to simply call the instance.Priority++. That would lead to quite an interesting result.

1
2
3
4
5
6
7
class Server
    {
        public Server(int tier, string name) {
            this.Name = name;
            this.Priority = (int)tier;
        }
    }
csharp

Enter Enums

If we want to create a more robust code, we should do the following. The None will represent a private machine used by the developer for work or other stuff.

1
2
3
4
5
6
public enum Tiers {
            None,
            Development,
            Testing,
            Production
        }
csharp

This is where the list of integer values concept comes into the picture. Behind the scenes, the enum assigned values to the labels starting from zero. How do we get values out of enums? This snippet reveals to you what values are associated with each item.

1
2
foreach (var level in Enum.GetValues(typeof(Tiers))) 
	{ Console.WriteLine("The tier: " + level + " has value of " + (int)level); }
csharp

The output will look something like this:

1
2
3
4
The tier: None has value of 0
The tier: Development has value of 1
The tier: Testing has value of 2
The tier: Production has value of 3
bash

If you want, you can break the order of the numbers which are assigned to each label.

1
2
3
4
5
6
public enum Tiers {
	None,
	Development = 10,
	Testing,
	Production
}
csharp

Re-enumerating the items gives us the following result. Meaning that, from the Development tier, we want to increase the value of the numbers starting from 10.

1
2
3
4
The tier: None has a value of 0
The tier: Development has a value of 10
The tier: Testing has a value of 11
The tier: Production has a value of 12
bash

This allows you to customize your enum as you please. This is very often used by game developers to store attack, class, or any other type of enumerable property our heroes may hold.

The first limitation we face with the standard enums is that they can only hold one value at a time. What happens if we want to add more Tiers to our servers, or other properties, and we want to have a combined server which is Production tier but, actually, the developers did some new functionality testing so the None also applies?

Bitwise Enums

A lot of developers use enums as described above, but there is more to it than meets the eye. The solution for the limitation posed by the standard enum comes in the form of Flags. Let's modify our original enum.

1
2
3
4
5
6
7
8
9
[Flags]public enum BitTiers {
	None = 1,
	Development = 2,
	Testing = 4,
	Production = 8,
	AlmostProd = Production | None,
	AlmostTestint = Testing | None,
	AlmostDevelopment = Development | None
}
csharp

In order to use the Flags, we need to use the single and combined values. For single values, they will be powers of two. The combined values will come from the logical or expression represented by the | character.

In order to understand this, we need to look at the binary values of these items for the original and the bitwise enum.

The values of the original in binary:

1
2
3
4
5
6
public enum Tiers {
	None,			//000000
	Development,    //000001
	Testing,        //000010
	Production      //000011
}
csharp

The values of the bitwise in binary:

1
2
3
4
5
6
7
8
9
[Flags]public enum BitTiers {
	None = 1,									//000001
	Development = 2,							//000010
	Testing = 4,								//000100
	Production = 8,								//001000
	AlmostProd = Production | None,				//001001
	AlmostTesting = Testing | None,				//000101
	AlmostDevelopment = Development | None		//000011
}
csharp

Let use this foreach to do the heavy lifting.

1
2
foreach (var level in Enum.GetValues(typeof(BitTiers)))
	{ Console.WriteLine("The tier: " + level + " has value of " + (int)level); }
csharp

Iterating over the values we can see the following output.

1
2
3
4
5
6
7
The tier: None has a value of 1
The tier: Development has a value of 2
The tier: AlmostDevelopment has a value of 3
The tier: Testing has a value of 4
The tier: AlmostTesting has a value of 5
The tier: Production has a value of 8
The tier: AlmostProd has a value of 9
bash

Where does the value of the Almost label come from? Let's take the AlmostTesting as an example.

It is made up of the logical or expression between 000100 (Testing) and 000001 (None). The truth table of the or logical operator is as follows.

ABA or B
011
101
111
000

The fact that you can either assign values for each label or let the constructor decide for you comes in handy when you want to create a configurable application with the magic of enums.

Conclusion

The enum is a powerful tool in the developers’ tool set. It allows us to write elegant and easy to understand code. The modification can be done with ease, as the data structure is easily extendable, but you don’t have to necessarily modify the code to add a new label for your enums. The special bitwise enums also provide capabilities and possibilities to restructure your code in a more flexible but yet durable way.

0