Associating Strings with enums in C#

I have seen other great articles out lining the benefits of some pretty clever and useful helper classes for enums. Many of these methods almost exactly mirror methods I had written in my own EnumHelper class. (Isn’t it crazy when you imagine how much code duplication there must be like this out there!)

One thing that I don’t see emphasized much is trying to associated string values with enums. For example, what if you want to have a Drop Down list that you can choose from a list of values (which are backed by an enum)? Lets start with a test enum:

public enum States
{
    California,
    NewMexico,
    NewYork,
    SouthCarolina,
    Tennessee,
    Washington
}

So if you made a drop down list out of this enum, using the ToString() method, you would get a drop down that looks like this:

image

While most people will understand this, it should really be displayed like this:

image

“But enums can’t have spaces in C#!” you say. Well, I like to use the System.ComponentModel.DescriptionAttribute to add a more friendly description to the enum values. The example enum can be rewritten like this:

public enum States
{
    California,
    [Description("New Mexico")]
    NewMexico,
    [Description("New York")]
    NewYork,
    [Description("South Carolina")]
    SouthCarolina,
    Tennessee,
    Washington
}

Notice that I do not put descriptions on items where the ToString() version of that item displays just fine.

How Do We Get To the Description?

Good question! Well, using reflection of course! Here is what the code looks like:

public static string GetEnumDescription(Enum value)
{
    FieldInfo fi = value.GetType().GetField(value.ToString());

    DescriptionAttribute[] attributes =
        (DescriptionAttribute[])fi.GetCustomAttributes(
        typeof(DescriptionAttribute),
        false);

    if (attributes != null &&
        attributes.Length > 0)
        return attributes[0].Description;
    else
        return value.ToString();
}

This method first looks for the presence of a DescriptionAttribute and if it doesn’t find one, it just returns the ToString() of the value passed in. So

GetEnumDescription(States.NewMexico);

returns the string “New Mexico”.

A Free Bonus: How to Enumerate Enums

Ok, so now we know how to get the string value of an enum. But as a free bonus, I also have a helper method that allows you to enumerate all the values of a given enum. This will allow you to easily create a drop down list based on an enum. Here is the code for that method:

public static IEnumerable<T> EnumToList<T>()
{
    Type enumType = typeof(T);

    // Can't use generic type constraints on value types,
    // so have to do check like this
    if (enumType.BaseType != typeof(Enum))
        throw new ArgumentException("T must be of type System.Enum");

    Array enumValArray = Enum.GetValues(enumType);
    List<T> enumValList = new List<T>(enumValArray.Length);

    foreach (int val in enumValArray)
    {
        enumValList.Add((T)Enum.Parse(enumType, val.ToString()));
    }

    return enumValList;
}

As you can see, the code for either of these methods isn’t too complicated. But used in conjunction, they can be really useful. Here is an example of how we would create the drop down list pictured above based on our enum:

DropDownList stateDropDown = new DropDownList();
foreach (States state in EnumToList<States>())
{
    stateDropDown.Items.Add(GetEnumDescription(state));
}

Pretty simple huh? I hope you find this as useful as I do.

One More Example

There is one more scenario that I often find myself needing to associate string values with enums – when dealing with legacy constant string based system. Lets say you have a library that has the following method:

public void ExecuteAction(int value, string actionType)
{
    if (actionType == "DELETE")
        Delete();
    else if (actionType == "UPDATE")
        Update();
}

(I tried to make this look as legacy as I could for a contrived example). What happens if somebody passes in “MyEvilAction” as a value for actionType? Well, whenever I see hard coded strings, that is a code smell that could possibly point to the use of enums instead. But sometimes you don’t have control over legacy code and you have to deal with it. So you could make an enum which looks like this:

public enum ActionType
{
    [Description("DELETE")]
    Delete,
    [Description("UPDATE")]
    Update
}

(I know, I know, this is a very contrived example) Then you could call the ExecuteAction Method like this:

ExecuteAction(5, GetEnumDescription(ActionType.Delete));

This at least makes the code more readable and may also make it more consistent and secure.

kick it on DotNetKicks.com

Advertisements

4 Responses to Associating Strings with enums in C#

  1. gabriel says:

    Great article, this is much needed for many functions, my only beef if that you may need several elements, one for the key in an external file (ie when parsing from XML for exmaple), and another for displaying the enum value… I might end up making the description attribute a comma-separated list of values, each “dimension” being used for a particular purpose. It’s a little dirty, but I have had projects with thousands of lines devoted to converting test to enums and vice versa…

    Thanks!

  2. Matt says:

    Great article. Good info and very well laid out. Thanks!

  3. Nelson says:

    Really good article. I’ve always created a bunch of functions to validate the value to show on the lists. Sweet and easy. Congrats.

  4. asp.net, c#,javascript…

    […]Associating Strings with enums in C# « Spontaneous Publicity[…]…

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: