The Power of Enum

One of the most overlooked tools in modern programming languages for producing elegant code is the enumeration.

The enumeration is such a simple concept, yet it yields such a high return in both readability and usability of your code.

The enum is able to eliminate the need for XML style comments for a parameter to a method, and prevent the passing of null in one fell swoop.

  • Enumerations make the set of choices for a parameter finite and self-describing.
  • Enumerations which are parameters can never be set to null.

    Explicit documentation becomes self-documentation

Let’s look at an example, so I can show you what I am talking about:

/// <summary>
/// Causes pacman to eat the specified fruit.
/// </summary>
/// <param name="fruit">A fruit which must either be an apple, banana, orange, or

/// cherries.</param>
public void Eat(string fruit)
{
    switch(fruit)
    {
        case "apple":
            Console.WriteLine("Ate an apple");
            break;
        case "banana":
            Console.WriteLine("I love bananas");
            break;
        case "orange":
            Console.WriteLine("A color and a fruit");
            break;
        case "cherries":
            Console.WriteLine("This one is plural");
            break;
        default:
            break;
    }
}

You can see here that we need some comment to tell the user of the method what can be passed into the fruit parameter.

We have to handle the default case, in case someone is able to pass in something we didn’t expect.

A simple typo in calling the method or in our method, could result in a difficult to find bug.

Someone can call this method with null like so:

// passing in null is allowed, strings can be null, objects can always be null.
Eat(null);

Now take a look at the example that uses an enumeration for fruits.

public void Eat(Fruits fruit)
{
    switch (fruit)
    {
        case Fruits.Apple:
            Console.WriteLine("Ate an apple");
            break;
        case Fruits.Banana:
            Console.WriteLine("I love bananas");
            break;
        case Fruits.Orange:
            Console.WriteLine("A color and a fruit");
            break;
        case Fruits.Cherries:
            Console.WriteLine("This one is plural");
            break;
    }
}

Do we really need the XML comment anymore?  When you try to call Eat() you will immediately see that it requires a Fruit and when you type “Fruit.” you will get:

SS-2010-05-08_11.49.39

Pretty self-explanatory.

Consider what happens when I try to pass null into the method.

SS-2010-05-08_11.51.22

You cannot do it.  No matter how hard you try.

Side note: before the comments start coming in.  The example above is using a switch statement so that it can be simple for demonstration.  In real code you would want to do something smarter here like use a Dictionary<Fruits, string> and replace the switch.

choices-760701

The power of limiting choices

It is a funny kind of a seeming contradiction that limiting the amount of choices increases the effectiveness of something.

The real power of enumerations to make your code more elegant lies in this contradiction.  By constraining the choices of what can be passed into a method, it becomes possible to list those choices out.  Which allows intellisense to display the choices for you.  You are forcing the IDE to document your code automatically.

Options that are self-discoverable are always going to be easier to use and understand, because they don’t require the mind to parse a human sentence and translate it into code.

Limiting choices protects your code in many other ways.  You prevent typos on either end because the compiler will now tell you if you have typed one of the choices wrong.

Testing becomes simpler, because the choices are finite.  Edge conditions and testing invalid input don’t apply to methods that take enumerations.  All input possibilities are known.

When to use enumerations

It is more often than you would think.  Let me show you an example where many people might not notice they could use an enum:

public void StartGame(int numberOfPlayers);

Many programmers would look at this code and not even think about using an enumeration here.  The number of players feels like an integer.

Every time you are writing a method and declaring the parameters, you should be asking yourself “How can I constrain the choices of what can be passed in?”

In this case, it is very simple.  How many players does the game allow?  There might even be a constant MAX_PLAYERS = 4.

We can very easily convert this code to use a simple enum and constrain the choices.

public void StartGame(PlayerCountSelection numberOfPlayers);

This small change may not seem like much, but it is going to immediately eliminate the need for writing unit tests to check for invalid player amounts being passed in, and it is going to prevent another programmer using this method from having to look in the documentation to find out the valid ranges of the int.

It is the culmination of limiting choices throughout your code that produces a net effect of reducing the complexity of the system.  It is the same with most of the best practices I suggest on this blog.

So when should you use enumerations?  Any time you can.  Any time you have the opportunity to constrain input choices, do it.

Combine them with maps and function pointers for the ultimate combo!

As always, you can subscribe to this RSS feed to follow my posts on elegant code.  Feel free to check out my main personal blog at http://simpleprogrammer.com, which has a wider range of posts, updated 2-3 times a week.  Also, you can follow me on twitter here.

19 thoughts on “The Power of Enum”

  1. @Adil Ahmad
    Sure, if we were doing this for a real application, we might have IFruit, and have an Apple, Orange etc class which all implemented a method Eat which had the different behavior.

    Of course, we should not automatically jump to that pattern to solve this problem, because the solution maybe much simpler and be easily solved with a dictionary that maps the type of fruit to the message.

    The point of this example was not to solve the problem of making the code as clean as possible, but to point out the use of an enum to improve that code as is. Perhaps I should have used a different example though.

  2. How about this???

    public enum Fruit{
    APPLE{
    public void print(){System.out.println(“i am apple”);}
    },
    ORANGE{
    public void print(){System.out.println(“i am orange”);}
    },MANGO{
    public void print(){System.out.println(“i am mango”);}};
    public abstract void print();
    }

    your eat() can now become

    public void eat(Fruit fruit)
    {
    fruit.eat();// no dirty switch case
    }

    This is in java.I hope kind of enum is possible in C#.

  3. First off, enumerations don’t constrain your set of choices e.g. if your Fruits enum “inherits from” the default of int you can pass this in to your method no problem: (Fruits)123456. Similarly Enum.Parse() will also accept “123456” as a valid value for Fruits. Enumerations simply allow you to give some of the values of, in this case, int a special meaning. It depends on how the values are getting into your system as to whether you’d ever need to worry about these unspecified values but it’s something you should be aware of.

    Secondly, I think the best solution to you first example is what Abinesh was getting at i.e. a more OO solution where you have an abstract Fruit class with an abstract Eat() method with Apple, Banana etc classes inheriting from it and implementing the Eat() method.

  4. I like enums as replacements for magic numbers, per Raymond Chen at the Old New Thing. Using ints, bools, and other basic types as function parameters is bad since you can’t tell from the source code line what the values are SEMANTICALLY. Enumeration values provide a way to document what was meant, not just pass a value.

  5. I also like how the switch-snippet in Visual Studio will automatically fill in all enumeration fields when you use it; e.g. switch-[TAB]-[TAB] fruits [TAB] [ENTER]

Comments are closed.