Enum’s are Evil – updated

In C# dotnet the class Enum is heavily used. Some geek’s argue that the Enum’s “improve code clarity and and reduce the probability of invalid values. … Enum’s are self-documenting.

I will show you, that Enum’s are in almost any cases just evil.

You don’t believe me? Read on…

What the MSDN documentation says about enum’s:

“The enum keyword is used to declare an enumeration, a distinct type that consists of a set of named constants called the enumerator list. Every enumeration type has an underlying type, which can be any integral type except char. The default underlying type of the enumeration elements is int. By default, the first enumerator has the value 0, and the value of each successive enumerator is increased by 1. For example:”

Strange Thing #1 – Evil

I removed this one, because VS.Net does show the enums in alphabetical order – my fault.

Strange Thing #2 – Evil

internal enum Color : short

Why would I define an enum as UInt32 or as Byte? I believe this is a legacy thing because the enum is mostly used to define the values for the Win32 API.

Strange Thing #3 – Evil

[Flags]
internal enum ParseFlags
{
  HaveYear  = 0x00000001,
  HaveMonth = 0x00000002,
  HaveDay  = 0x00000004
}

Why do we need to define the “Flags” attribute to get 32 on/off values? Why must the values of a Flags attribute be the power of 2. That will not be enforced and leads to errors when you define for example a value of 3 in the example above.

#4 – No Type Safety – Evil

If you think enum’s are type safe, you will get into deep trouble. Look at the example code below. The enum that we have defined is 1, 2 and 3. Right?
Now try to call

new EnumTricks.IsVolumeHigh((Volume)27);

That should fail, at least at runtime. It didn’t? That’s really strange… The wrong call will not be detected during compilation nor during runtime. You feel yourself in a false safety.

public enum Volume
{
  Low = 1,
  Medium,
  High
}

public class EnumTricks
{

  public bool IsVolumeHigh(Volume volume)
  {
    var result = false;

    switch (volume)
    {
      case Volume.Low:
        Console.WriteLine("Volume is low.");
        break;

      case Volume.Medium:
        Console.WriteLine("Volume is medium.");
        break;

      case Volume.High:
        Console.WriteLine("Volume is high.");
        result = true;
        break;
    }

    return result;
  }
}

Solution: Use Enum.IsDefined to find out, if the int value is in the defined range of the enum value.

#5 – Conversion – Evil

Have you ever tried to convert from enum to int, int to enum, string to enum, string to int value of enum? I’ll show you here with the Volume enum from above, but I didn’t check for the:

public int EnumToInt(Volume volume)
{
  return (int)volume;
}

public Volume IntToEnum(int intValue)
{
  return (Volume)intValue;
}

public Volume StringToEnum(string stringValue)
{
  return (Volume)Enum.Parse(typeof(Volume), stringValue);
}

public int StringToInt(string stringValue)
{
  var volume = StringToEnum(stringValue);
  return EnumToInt(volume);
}

#6 – Bad Changeability – Evil

Imagine the following phone call between Frank, a customer, and Darren the developer.

Frank: Hi Darren; I need a new value for the person status about his financial standings. We have currently Low, Medium and High, but we need ‘undefined’ as a new value.

Darren: I see.

Frank: When can you implement that?

Darren: Uups Frank. We just finished our sprint this week. The earliest we can plan this is for the sprint after the current one. That takes about 5 weeks.

Frank: What? It’s just another value not a whole new functionality!

Darren: Calm down Frank; we have these cool enum’s in place that saved us a lot of development time. To extend them I have to add it in the code and create a new build. We have to plan it for the next sprint.
Frank: Are you nuts? I don’t know what you talking about. I’m an ordinary user and just want to have another value on the user interface.

Darren: Sorry for that. I can’t do it earlier.

What would you think as a developer? I would feel messed around.
So enum’s are really evil, if you need to extend them. Or did you ever thought about using enum’s for the Swiss zip code system?

If you must ensure your enumerations are extensible, you have to find another solution. One alternative solution is the usage of reference codes. With reference codes you have a code (your identifier) and a value that you will use to show to the user. For example the currencies as defined in the ISO standard define a classical reference code. The list of possible values can be stored in the database or in a file, which both are easy to extend and update.

#7 – Usage of Enum’s – Evil

What are the enum’s used for in real projects? Often they are used to control the behavior of methods within classes.

public enum Configuration
{
  Debug,
  Release
}

public class Logger
{
  public void Log(Configuration configuration, string logMessage)
  {
    switch (configuration)
    {
      Debug:
        InternalLog("DEBUG: " + logMessage);
        break;

      Release:
        InternalLog(logMessage);
        break;
    }
  }

  private void InternalLog(string logMessage)
  {
    ...
  }

}

This could easily be rewritten (I leave it to you as an exercise to fully implement the example):

public class DebugLogger : AbstractLogger
{
  ...
}

public class ReleaseLogger : AbstractLogger
{
  ...
}

When are Enum’s not so Evil?

Every time you have a fixed list of integer values which are not used to control your flow of instructions, you may use an enum. We could discuss the usage for the gender (Male, Female, Undefined) or for month of the year (January, February … December). But with the last example I already have the bad feeling of internationalization. Will the string representation of the enum represent the key for the resources?

Conclusion

A long article where I tried to animate you to think more about the usage of enum’s in your every day coding, because Enum’s are still just evil.

See also Urs Enzler’s article about Top 10 of Software Design Evilness.


About the author

15 comments

  • What a load of piffle.

    Anything that can be used badly can be used badly. So what. Enums do help document. Just because some people don’t bother to learn how they work properly doesn’t mean that they are evil.

    I reckon you have just bothered to read up on enums and have found why your badly written code doesn’t work and want a rant. Let’s go through your points.

    Strange Thing #1:

    You must be angry or something not to realise that the Intellisense is indeed in alphabetical order.

    Strange Thing #2:

    Why define as a different type? Perhaps because you are interfacing with something that uses a different type. Perhaps you want to use a smaller value to minimise memory usage?

    Strange Thing #3:

    You don’t have to specify the flags attribute. You can still use the logical bitwise operators. If you do define Flags you get a couple of extra nice features, such as the conversion to string working properly for combined values.

    No Type Safety:

    Who ever said they were type safe? Why is this a problem as long as you understand? If you can’t be bothered to learn something properly, expect it to bite you.

    Conversion:

    What’s wrong with this?

    Bad Changeability:

    Nope, this guy’s a bad developer. Are you suggesting that the developer did a good job when he defined an enum that could not be extended? Or he created a system that was locked into enums and didn’t consider that the system may need an extra value? Fire him, he’s an idiot.

    Usage of Enums:

    Again, fire this guy. That’s a stupid use of enums. Or maybe send him on a course. I reckon I can take any part of a language and use it inappropriately. Does that make every language bad?

    Even your example of good usage suggests a bizarre loathing of a good concept. Why would you care about internationalisation when creating an enum. These are CONSTANTS for use internally, not strings for display to the user.

    Bad article, bad opinion, not well thought out.

  • #1: Not Enum’s fault.
    #2: Nonsensical.
    #3: Missing the point.
    #Bad Changeability: Huh?
    #Usage: Not Enum’s fault.
    #When not evil: Contradictory, see #3.

  • To say that enums are evil may be a bit provocative, but Enums are mostly not the best solution to solve a problem.
    If you have to control behaviour then use subclassing instead of switch case.
    If you have to identify a property then use reference codes.

    You can use enums, but the other options are much easier and powerful regarding extensibility, maintainability and readability.

    And using a sub-optimal solution although there is an obvious better one is defenitly evil 😉

    Using enums is like using a hammer for everything, instead of using a screw driver or scalpel when best suited.

  • @Urs,

    of course enums are mostly not the best solution to a problem. They are a solution to some problems though. I think in general that this article is rather ridiculous.

  • Hy guys
    Interesting how this provocative article manages to seethe a discussion on our website. I really appreciate all the comments you guys are currently giving about this topic. But I must say that some of the comments are rather rude against the author. Please consider that the article is reflecting the author’s opinion about enums. Some agree and some might not agree…

    I personally think of enums not as plain evil programming construct but I think that enums can be safely used in code structures internally. Especially for frameworks that should be designed for extensibility the usage of enums should be avoided because polymorphism is the way to go.

    Looking forward for more controversial discussion 😉

    Daniel

  • If your any additional values would require your application to change, then you need a constant, or Enum for that matter. Example, addition of status to a certain type of record, which probably needs extra logics.

    If any addition of additional values should not affects how the application works (as in, just another value), then use reference files. Example, additional ISO currency value, which should not affects on how the application works.

    And one should not expose internationalization concerns to Enums. That’s just plain bad design IMO.

  • Hi, we are sorry that you didn’t like this article. If you would like to express your thoughts so that we can learn why you didn’t like it then don’t hesitate to give a comment here.

  • I can assure you that I hate enums as well. They have no place in an object oriented language.
    Every time I see enums used, a lot of spaghetti code has evolved around it because they simply are very stupid to build anything useful around.

    Enums should be removed from C#.

  • #6: Frank “just wants a new value on the interface”, but Darren doesn’t even know what that value is supposed to *mean* to the application. What should the application *do* when that value is encountered? Should it max out the speaker volume? Mute it? Treat it as though it were set to some system-wide default?

    Enums are ‘evil’, because Darren doesn’t allow a client to demand an immediate code change with no specification about what that change will *do*? Or because he won’t do it immediately, without any testing, or sign-off procedure?

    Seriously, as nonsensical as many of those complaints about Enums were, *that* one takes the cake.

  • My brother pointed me to this when he asked if using an enum in a switch statement for control flow was bad code. Every one of the examples of “evil” are based on a developer who didn’t know what they were doing or potential use is an absurd way. Enum classes would be a nightmare in certain situations such as serialization. They’re massively bloated, require 10 times more work, and not as maintainable compared to a regular enum and do not work a single bit better for things like control flow. We use them in WCF, mobile clients and other web services without issue for years now where millions upon millions of transactions are processed. Not a single time has anyone said or even hinted “oh my, we used an enum and it hosed us”.

    Yes, enum classes have their place but making a blanket claim IMO displays a serious lack of knowledge or experience in the real world.

By Thomas

Recent Posts