Monday, January 19, 2009 8:36 PM grant.barrington

EnumHelper - Getting a Friendly Description from an Enum

Wherever possible we use enumerations in our applications. Often the name of the enumeration isn't what you want to print on the screen. It could be because the enumeration is 2 words that have been joined together, or you want the description to start with a number (not that we do this... but you could).

Example

You might have a enumeration for Colours that a user is allowed to select from. The values available for this enumeration may be (hypothetically):

  • Burnt Orange
  • Bright Pink
  • Dark Green
  • Sky Blue

To define this in code, you'd use an enumeration like this:

public enum UserColours
{
    BurntOrange = 1,
    BrightPink = 2,
    DarkGreen = 3,
    SkyBlue = 4
}

The Problem

Normally, in an ASP.NET application we'd render an enumeration as a Drop Down List. Problem is we don't want to show "BurntOrange" as a value in the drop down list, we want to show a nice friendly option like "Burnt Orange".

The Solution

We've created a static helper class that uses reflection to get a Description for each member of the enumeration. I've also got this as an extension method for ASP.NET 3.5. This post is for the helper class, but it can very easily be converted to an extension method for ToString().

To get a friendly name, we decorate each member of the enumeration with the DescriptionAttribute from the namespace System.ComponentModel. Our enums end up looking like this:

using System.ComponentModel;

namespace Ellington.EnumHelperExamples
{
    public enum UserColours
    {
        [Description("Burnt Orange")]
        BurntOrange = 1,

        [Description("Bright Pink")]
        BrightPink = 2,

        [Description("Dark Green")]
        DarkGreen = 3,

        [Description("Sky Blue")]
        SkyBlue = 4
    }
}

When we need to then retrieve the friendly name from the enum, we have the following helper class:

using System;
using System.ComponentModel;
using System.Reflection;

namespace Ellington.EnumHelperExamples 
{
    public static class EnumHelper
    {
        /// <summary>
        /// Retrieve the description on the enum, e.g.
        /// [Description("Bright Pink")]
        /// BrightPink = 2,
        /// Then when you pass in the enum, it will retrieve the description
        /// </summary>
        /// <param name="en">The Enumeration</param>
        /// <returns>A string representing the friendly name</returns>
        public static string GetDescription(Enum en)
        {
            Type type = en.GetType();

            MemberInfo[] memInfo = type.GetMember(en.ToString());

            if (memInfo != null && memInfo.Length > 0)
            {
                object[] attrs = memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);

                if (attrs != null && attrs.Length > 0)
{ return ((DescriptionAttribute)attrs[0]).Description;
} } return en.ToString(); }

}

}

Now, when we want to get the friendly name from the enum, all we do is call:


EnumHelper.GetDescription(UserColours.BrightPink);

The code above, basically takes in the enumeration, uses Reflection to find the "DescriptionAttribute" on the member, and then returns the Description. If the DescriptionAttribute is not present on the enum, then we just call a ToString() on the enum to get the name.

As we're not hitting anything that is scary from a security point of view, the whole thing works in a partial trust environment.

Filed under: ,

Comments

# re: EnumHelper - Getting a Friendly Description from an Enum

Monday, January 19, 2009 11:56 AM by SGWellens

That is cool.

# re: EnumHelper - Getting a Friendly Description from an Enum

Monday, January 19, 2009 1:23 PM by Yev Bronshteyn

It's a nice idea, but there seems to be an element of duplication between the name of an enum option and a description. Perhaps the helper could, as an alternative option, perform a "pascal-to-English" conversion by adding a space before every capital letter that is either preceded or followed by a lowercase letter (except for the first). Just a thought.

# re: EnumHelper - Getting a Friendly Description from an Enum

Tuesday, January 20, 2009 3:49 AM by Steve Crane

Nice little helper class.  I think making GetDescription an extension method makes for slightly cleaner calling code though.

public static string GetDescription(this Enum en) { … }

allowing calls like

UserColours.BrightPink.GetDescription();

# re: EnumHelper - Getting a Friendly Description from an Enum

Tuesday, January 20, 2009 3:54 AM by ilivewithian

I like the idea, but how fast is it? Won't this be fairly slow?

# re: EnumHelper - Getting a Friendly Description from an Enum

Tuesday, January 20, 2009 6:46 AM by Richard

Interesting idea, but it opens the possibility for something like this:

[Description("Bright Green")]

BurntOrange = 1

Would it not make more sense to simply split the ToString into words, maintaining the relationship between the enumeration and its string representation?

# re: EnumHelper - Getting a Friendly Description from an Enum

Tuesday, January 20, 2009 11:21 AM by AndrewSeven

What about globalization and localization?

I've previously used an extension method to get the enum's description from a resource file so that additional languages only require you to add the appropriate resources.

# re: EnumHelper - Getting a Friendly Description from an Enum

Tuesday, January 20, 2009 12:11 PM by freddy

Nice and simple.

change the signature to: public static string Description(this Enum en)

and now you use it like:

UserColours.BrightPink.Description();

# re: EnumHelper - Getting a Friendly Description from an Enum

Tuesday, January 20, 2009 4:52 PM by Matt Freeman

[quote]

I like the idea, but how fast is it? Won't this be fairly slow?

[/quote]

What type of metric are you looking for? This will be the last of your concerns when you factor in other boundary IO (network, database) etc.. True there is a performance hit for reflection but I bet you could get a four figure per second answer if testing in isolation. More to point you need to concern how clean this is. It seems like UI literals are sitting on what could be part of your model, perhaps one should store this reference data in a cache and iterate over the enum to build said cache once per application startup.  

# re: EnumHelper - Getting a Friendly Description from an Enum

Tuesday, January 20, 2009 9:47 PM by grant.barrington

Thanks for feedback and comments... I'll try to reply in turn to everyone.

@punkcoder - I've omitted it from this post (don't want to try to do too much in one post), but our helper class also has a couple of other methods. One returns the enum as a ListItem, getting Value and Text. The other returns a ListItemCollection. We can then bind this directly to a DropDownList.

@Yev Bronshteyn & @Richard - You could do this, but you can't express some things as enums this way. eg you can't start an enum with a number and I'm not sure that you'd be able to have special characters in enums. This being the case, using a Pascal-to-string type method, you wouldn't be able to express "$5 million" as an enum or "#3" for example.

@ilivewithian - using reflection is never FAST, but for us its fast enough. If you wanted, you could introduce caching in the "GetDescription()" method to speed things up a bit

@Mike - nice work... I think we're roughly doing the same thing... nice work using generics though!!!

@Jas & @Sean - I'm just getting it out there what I do... there are probably a whole bunch of different ways to do this. I've seen people create their own attribute and use a method similar to this, store the values in the database and lookup at run-time, even put the whole enum in a massive switch statement and return the string.

@AndrewSeven - re: Globalization and Localization. You could probably use the method I have above, but using the namespace and the value, go and try to lookup a resx file first for a specific culture. If that doesn't exist, then run down into my code, returning the Description attribute if it exists, then just the ToString() if it doesn't

Grant

# re: EnumHelper - Getting a Friendly Description from an Enum

Friday, May 14, 2010 5:01 PM by Acupedunsunse

thanks! :)

lets write them until the admit it, or stop doing it! i am writing them now!

:)

# re: EnumHelper - Getting a Friendly Description from an Enum

Monday, June 7, 2010 12:49 PM by inoreixerfinc

Great tips! I will try it definitely

thanks for sharing this!

# re: EnumHelper - Getting a Friendly Description from an Enum

Monday, May 23, 2011 10:55 AM by Tom D

Or if you prefer the shorthand nature of linq:

public static string GetDescription(this Enum value)

   {

     return (from m in value.GetType().GetMember(value.ToString())

             let attr = (DescriptionAttribute)m.GetCustomAttributes(typeof(DescriptionAttribute), false).FirstOrDefault()

             select attr == null ? value.ToString() : attr.Description).FirstOrDefault();

   }

# re: EnumHelper - Getting a Friendly Description from an Enum

Friday, July 15, 2011 8:20 AM by dasari_ramacharan

thansk for the cool post

# re: EnumHelper - Getting a Friendly Description from an Enum

Friday, September 23, 2011 3:51 AM by Raja.Dev

A VERY GOOD EXPLANATION