Udostępnij za pośrednictwem


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    {        publicstaticstring ToDescription(thisEnum 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

  • Anonymous
    October 20, 2005
    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.

  • Anonymous
    October 20, 2005
    According to the latest spec including Extension properties and events are in consideration. Lets hope they finally make it to the product

  • Anonymous
    July 26, 2006
    As I had previously said I love extension methods and have started using them at multiple places...

  • Anonymous
    February 03, 2008
    My initial impression of extension methods was that they would lead to confusing code. I imagined other

  • Anonymous
    May 06, 2008
    Me he encontrado en el blog de Fresh Logic Studios con un post donde describen una técnica interesante

  • Anonymous
    June 22, 2008
    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();        }

  • Anonymous
    February 22, 2009
    I saw two posts on Enums today on Eric Lipperts and Chris Rathjen's blog. Enums are significantly different

  • Anonymous
    June 16, 2009
    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 }