What would you rather see? 1, 2, 3, or red, green, blue? Enums allow you to give meaningful names to values. Seems simple, right? It is, except for a few things you should be aware of.

This episode explains the following six aspects of enums that you need to be aware of in order to use them properly:

  1. Can you declare the underlying storage type that will be used? Some languages allow this and some just use an int. And some like early versions of C++ would try to use an int but could use something else if an int wasn’t large enough.
  2. Can you specify the enum values themselves? There are times when the exact values are important. What if you want different names for the same value? Or maybe you need to interface with some other code that uses specific values and you need to make sure that your code matches.
  3. What scope do the enum values occupy? This is important to understand so you know how to handle name conflicts if any. Early version of C++ would promote the enum values to the scope that the enum itself is declared in. Actually, C++ still does this but added a new enum class type that keeps the enum values scoped inside the enum.
  4. Will enum values convert to integers automatically? This is critical to understanding how you can use enums. If you ever want to combine enum values or save them to another type such as an int, then what will the compiler do?
  5. Can a variable of the enum type hold values not declared in the enum? If you have an enum that defines only red, green, and blue with the values of 1, 2, and 3, then is it possible to have a variable of this type that contains the value 5? You’d have to perform a cast to get the value 5 into the enum but most languages will allow this. You should never assume that just because you’re using an enum that you will know the values it will contain. It’s still wise to check ranges and have default switch statements in place to catch unexpected values.
  6. Can the enum type be used for flags? The older C++ enum type could support this because of the way it allowed conversion to ints automatically. Because the newer enum class type doesn’t work like this, then flags will be better implemented with another method. Consider using the bitset class. For C#, you can add an attribute called Flags that will let the compiler know you intend to use the enumeration to hold flags.

Listen to the full episode or you can read the full transcript below.

Transcript

The first thing to understand is that different languages usually have some concept of declaring enumerations or enums for short but there are differences.

Before we begin, what’s so bad about just using numbers? Well, the first thing is that you’ll probably want to use specific numbers consistently throughout your application. It would be very bad if part of your code thinks 1 means run very fast while another part thinks 1 means to stop and hide.

You can help solve this by declaring constant ints for each of the various meanings you want to represent. Then use those constant ints instead of the values directly. This will at least make sure that your hero runs consistently.

But the values are still ints. Just because you’re using some specially named values isn’t enough to enlist the compiler’s help to make sure that you don’t accidentally assign a constant describing a type of shrubbery to your hero’s movement. Since everything’s an int, the compiler can’t help.

The biggest advantage you get with an enum then is the addition of a new type. You can group values together that make sense together.

Enums allow you to move away from sprinkling raw numbers throughout your code, allow you to refer to these raw numbers with meaningful names instead, and allow you to group these names into their own type.

They’re definitely the sort of thing that can make your code easier to read and more reliable. There’s some details to be aware of though that I’ll describe right after this message from our sponsor.

( Message from Sponsor )

Here are six questions to ask about enums in your language. Knowing these six aspects will help you make better and proper use of your enums.

#1 Can you declare the underlying storage type that will be used? Some languages allow this and some just use an int. And some like early versions of C++ would try to use an int but could use something else if an int wasn’t large enough. If your language doesn’t allow the storage type to be declared and doesn’t have a type that it always uses, then you won’t be able to forward declare your enums. If you want to use an enum as a method parameter, then being able to declare the enum ahead of time really helps simplify your code. Also, if you have an enum with just a few values, then being able to specify the storage type will allow you to use less memory.

#2 Can you specify the enum values themselves? The whole point of an enum is so you can stop worrying about the specific values, right? So why is this important? Well, that’s not the whole point. Sure, you want to work with names instead of numbers. But there are times when the exact values are important? What if you want different names for the same value? Normally, this might lead to confusion. But used carefully, it can really help. For example, you could have the colors red, green, and blue, and another value called default that has the same value as red. Or maybe you need to interface with some other code that uses specific values and you need to make sure that your code matches. You need to use enums for all the normal reasons but in this case, you really do care about the number values also.

#3 What scope do the enum values occupy? This is important to understand so you know how to handle name conflicts if any. Early version of C++ would promote the enum values to the scope that the enum itself is declared in. Actually, C++ still does this but added a new enum class type that keeps the enum values scoped inside the enum. Why is this important? Well, the earlier example that used a default value name is a good pattern that you might want other enums to follow. But you can’t have multiple enum values all called default if they’re all in the same scope. You may have to name your enum values so they’ll all be unique. This is why so many C++ enum values have strange prefixes in the names. They need to be unique.

#4 Will enum values convert to integers automatically? This is critical to understanding how you can use enums. If you ever want to combine enum values or save them to another type such as an int, then what will the compiler do? The enum types in C++ can be assigned to an int without a cast. But the new enum class type will not. And is it possible to convert an int to an enum? How? For example, in C#, you can make use of the System.Enum methods including the Parse method to convert an int to an enum.

#5 Can a variable of the enum type hold values not declared in the enum? If you have an enum that defines only red, green, and blue with the values of 1, 2, and 3, then is it possible to have a variable of this type that contains the value 5? You’d have to perform a cast to get the value 5 into the enum but most languages will allow this. You should never assume that just because you’re using an enum that you will know the values it will contain. It’s still wise to check ranges and have default switch statements in place to catch unexpected values.

#6 Can the enum type be used for flags? First, you should know what a flag is and why you might want flags instead of normal values. If you have an enumeration that represents something that can only take on a single value at a time, then you can just name your enum values as normal and use them just like a named integer value. But what if you want something that can be combined in various ways? Maybe you want to keep track of the state of your hero with a single value that can be a combination of things like wounded, well fed, and tired. If you have many such states, then the possible number of combinations would be too many to try to specify all of them. By using them as individual flags that can be turned on of off, they can be stored in the same enum with a little extra care. The main thing is to carefully select values so they don’t overlap. The older C++ enum type could support this because of the way it allowed conversion to ints automatically. Because the newer enum class type doesn’t work like this, then flags will be better implemented with another method. Consider using the bitset class. For C#, you can add an attribute called Flags that will let the compiler know you intend to use the enumeration to hold flags.

Whatever programming language you’re using, understanding the previous 6 aspects of enums will go a long way to helping you use them effectively.