C# 3.0 : using extension methods for enum ToString


In my previous blog I was trying to address the issue that when ToString is called on an enum the literal string for the enum constant is returned. Custom attributes can be used to tag localizable description string to the constants so that you can write functions that use reflection to get to the attribute and show that string. However this has a significant disadvantage as you need to write code as follows

enum Coolness {

[DescriptionAttribute(“Not so cool”)]

NotSoCool = 5,

[DescriptionAttribute(“Very cool”)]

VeryCool = NotSoCool + 7,

}

class Program

{

static string GetDescription(Enum en)

{

// Uses reflection to get the attribute and returns it

}

static void Main(string[] args)

{

Coolness coolType = Coolness.VeryCool;

Console.WriteLine(GetDescription(coolType));

}

}


Calling GetDescription method on the enum is definitely not intuitive. This is why I had said that I love extension methods. Converting this to use C#3.0 extension method makes its intuitive and it’ll be easy for the developer to remember that in the same lines as ToString there is also a ToDescription on enums.

using System;

using System.Reflection;

using System.Collections.Generic;

using System.Text;

using System.Query;

using System.Xml.XLinq;

using System.Data.DLinq;

using System.ComponentModel;

// C# 3.0 syntax used…

namespace FunWithEnum

{

enum Coolness

{

[DescriptionAttribute(“Not so cool”)]

NotSoCool = 5,

Cool, // since description same as ToString no attr are used

[DescriptionAttribute(“Very cool”)]

VeryCool = NotSoCool + 7,

[DescriptionAttribute(“Super cool”)]

SuperCool

}

static class ExtensionMethods

{

public static string ToDescription(this Enum en) //ext method

{

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();

}

}

class Program

{

static void Main(string[] args)

{

Coolness coolType1 = Coolness.Cool;

Coolness coolType2 = Coolness.NotSoCool;

Console.WriteLine(coolType1.ToDescription());

Console.WriteLine(coolType2.ToDescription());

}

}

}


 

Comments (8)

  1. mabster says:

    Very nice. Can extension methods be properties (I know that sounds weird given that they’re called "extension methods")?

    If so, you could define a "Description" property rather than the (kind of awkward-looking) ToDescription() method.

    At the very least I think I would call it "ToDescriptionString" (similar to DateTime’s ToShortDateString method), or possibly just "GetDescription".

    Extension methods are going to change things in a big way, that’s for sure.

  2. According to the latest spec including Extension properties and events are in consideration. Lets hope they finally make it to the product

  3. As I had previously said I love extension methods and have started using them at multiple places…

  4. My initial impression of extension methods was that they would lead to confusing code. I imagined other

  5. Me he encontrado en el blog de Fresh Logic Studios con un post donde describen una técnica interesante

  6. Sergey says:

    I’ve created another

           public static string ConvertToString(this Enum value)

           {

               if (value == null)

                   throw new ArgumentNullException("value");

               Type type = value.GetType();

               FieldInfo fieldInfo = type.GetField(Enum.GetName(type, value));

               var descriptionAttribute =

                   (DescriptionAttribute)Attribute.GetCustomAttribute(

                                              fieldInfo, typeof(DescriptionAttribute));

               if (descriptionAttribute != null)

                   return descriptionAttribute.Description;

               return value.ToString();

           }

  7. I saw two posts on Enums today on Eric Lipperts and Chris Rathjen’s blog. Enums are significantly different

  8. Michael says:

    Here is a better implementation… takes care of caching so reflection does not take such a huge hit.

    public static class EnumExtensionMethods

    {

    #region [ Fields ]

    private static Dictionary<string, string> _enumTypeDescriptionCache = new Dictionary<string, string>();

    private static object _enumTypeDescriptionCacheLock = new object();

    #endregion

    #region [ Methods ]

    /// <summary>

    ///

    /// </summary>

    /// <param name="en"></param>

    /// <returns></returns>

    public static string ToDescription(this Enum en)    

    {

    string cacheKey;

    string description;

    cacheKey = string.Format("{0}:{1}", en.GetType().FullName, en.ToString());

    description = string.Empty;

    if (_enumTypeDescriptionCache.ContainsKey(cacheKey) == false)

    {

    lock (_enumTypeDescriptionCacheLock)

    {

    if (_enumTypeDescriptionCache.ContainsKey(cacheKey) == false)

    {

    MemberInfo[] memberInfo;

    memberInfo = en.GetType().GetMember(en.ToString());

    if (memberInfo != null && memberInfo.Length > 0)

    {

    object[] attributes;

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

    if (null != attributes && attributes.Length > 0)

    {

    description =((DescriptionAttribute)attributes[0]).Description;

    }

    }

    }

    else

    {

    description = _enumTypeDescriptionCache[cacheKey];

    }

    }

    }

    else

    {

    description = _enumTypeDescriptionCache[cacheKey];

    }

    return description;

    }

    #endregion

    }