Semi-Random Thoughts about .NET Enums

Semi-Random Thoughts about .NET Enums

Enums are an essential part of the .NET Framework -- something that we've all used for years. So in this commentary, I thought I'd wander through a handful of semi-random thoughts that I've had on enums. Some of these thoughts are mostly baked, some half-baked, and one isn't quite ready to go in the oven. I'll let you figure out which ones are which.

RandomThought.TheFirst: A .ToEnum() Extension Method

I still vividly remember how obtuse it felt to cast a string into an enum when I first got started with C#. For example, let's suppose I had the following enumeration:

public enum Importance

{

    None,

    Trivial,

    Regular,

    Critical

}

Then assume that I wanted to translate some text loaded from a file, the database, or elsewhere into 'Importance.' The code would look like the following line of code:

string input = "Regular";

Importance importance = (Importance) Enum.Parse(typeof(Importance), input, true);

This line of code is something that I've always found utterly obtuse. Yes, I get what's going on there. I even get why it's needs to be so explicit. But I also can't help but think that typing this out is clunky and that some syntactic sugar in this regard would have been a nice feature early on.

At any rate, I thought it would be nice to just wire up an extension method that would let me do something like stringValue.ToEnum(); as a means of bypassing all of the syntactic clunkiness of what's currently required.

Here's what I ended up with when using generics:

public static E ToEnum<E>(this string input, bool strict)

{

    if (!strict)

    {

        if (!Enum.IsDefined(typeof(E), input))

            return default(E);

    }

    return (E)Enum.Parse(typeof(E), input, true);

}

And here's an example of it being used:

Importance importance = "Regular".ToEnum<Importance>(true);

Granted, it's nothing super fancy or earth-shattering -- but it's a ton less typing. And I vastly prefer it to Enum.TryParse<E>(input) as well. As implemented, my approach also defines whether or not sending in an importance of "Monkey" would result in an output of Importance.None (the default) or would result in an exception, which is what's going on with the strict argument I've defined.

RandomThought.TheSecond: Enums are Kind of Weak

More than once during my career as a .NET developer I've also run into situations where I couldn't help but think that .NET enums are a little bit like 'weak sauce' -- just not quite as powerful as they might be. Happily, much smarter people than I have also thought very similar things, such as Jon Skeet who has blogged as much.

In my mind, however, enums really serve two primary needs or benefits. On one hand they're exactly what their name states: an enumeration or listing of all possible, allowable values within a given domain. For example, with the Importance enum that I defined above, the notion of an enum outlines exactly which 'importances' are valid by clearly enumerating each and every permissible member of a given domain.

But I also find that enums serve another value as well -- in that they're a fantastic tool that helps prevent confusion around magic numbers while protecting developers from typos. For example, I commonly use the following construct in my ASP.NET MVC applications:

public static class TempData

{

    public static string Error = "Error";

    public static string Message = "Message";

}

It's admittedly cheesy, but it allows me the option to pick up 'strongly-typed happiness' in my application. Within my controller actions, I never have to worry about missing a 'message' in one of my views by doing something dumb such as the following:

TempData["Ernor"] = "Woops. Note the typo...";

To some degree, I wish there was better support for situations like this. It would be nice to potentially even allow certain types of inheritance or extensions of enums. Although that also seems simultaneously insane because it would make sense to potentially allow classes and objects higher up in your hierarchy to define, say, new Importance types, the reality is that you would then have existing code that had a different definition of all allowable and possible enumerations that'd now be confronted with new definitions. So the short story is that I have some weird, deep, inner yearnings that lead me to believe that enums could be more powerful and might even be extensible, but I haven't quite gotten to a point where I can elucidate where I'd even start.

RandomThought.TheThird – Enums as a Potential Code Smell

Finally, the most important thought I can share about enums is that they're easy to abuse. For example, I recently came across this great blog post outlining the notion of name smells, where the last smell defined specifically targets ways in which enums can commonly be a marker for poorly defined code where polymorphism is simulated instead of explicitly implemented.

Happily and candidly, this particular 'name smell' couldn't have found me at a better time either -- as I was, in fact, struggling with a bit of code that was using poor-man's inheritance (i.e., gobs of switches) and keeping up with this code was starting to drive me nuts. (I don't claim to know everything about development -- as I am, after all, a SQL guy or that's my excuse.) A few hours later, and after a review of some design patterns, I ended up being able to gut huge amounts of my code, and wound up with code that was not only much easier to maintain and manage as new logic or operations needed to be added, but also were much more intuitive as well.

Hide comments

Comments

  • Allowed HTML tags: <em> <strong> <blockquote> <br> <p>

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
Publish