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 productAnonymous
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 otherAnonymous
May 06, 2008
Me he encontrado en el blog de Fresh Logic Studios con un post donde describen una técnica interesanteAnonymous
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 differentAnonymous
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 }