C# : Enum and overriding ToString on it


I saw two posts on Enums today on Eric Lipperts and Chris Rathjen’s blog. Enums are significantly different from the other types and people run into unusal problems while working with them.


C++


The CLI enum is considerably different from the native C++ enum and therefore you need to be careful how you define and use them in Managed C++. In new syntax (C++/CLI whidbey) the following code compiles even though both the enums define the same name Cool.

enum class Coolness // class indicates this is a C++/CLI enum

{

NotSoCool,

Cool,

SuperCool

};

enum class TempRange

{

Cool,

Hot,

VeryHot,

};


In old syntax (pre whidbey) you need to define the enum as __value enum Coolness. In case you drop the class then you are using the native C++ enum and according to C++ specification the enumerator declarations are promoted to the same scope as the enumerated type declaration and the code will fail to compile pointing out a redefinition of Cool.


C#


In C# we do need not care about these as there is only one definition of enum which is that of the CLI enum.


Common things like the first enum member get the value 0, the value of a subsequent member is calculated by adding 1 to the member textually preceeding it, you can assign values explicitely to a enum member are well-known. However there are some not so well known usages as well.

enum Coolness : byte

{

NotSoCool = 5,

Cool,

VeryCool = NotSoCool + 7,

SuperCool

}

Coolness coolType = Coolness.VeryCool;

Console.WriteLine(“Underlying type: {0}”, Enum.GetUnderlyingType(coolType.GetType()));

Console.WriteLine(“Type Code : {0}”, coolType.GetTypeCode());

Console.WriteLine(“Value : {0}”, (byte)coolType);


By default the compiler uses Int32 to store the enum members. Here we are asking it to use byte. VeryCool uses a reference to the NotSoCool and will get the value 12. So the out put of the code above will be


Underlying type: System.Byte
Type Code      : Byte
Value          : 12


Since all enums have System.Enum as the abstract base type, a lot of funcionality becomes available to get details about the enum type.


If you want to print the value of the enum then it can be done in the following ways

Console.WriteLine(coolType.ToString(“G”)); // name of the constant

Console.WriteLine(coolType.ToString(“F”)); // name of the constant

Console.WriteLine(coolType.ToString(“X”)); // value is hex

Console.WriteLine(coolType.ToString(“D”)); // value in decimal


Output:
VeryCool
VeryCool
0C
12

F and G gives the same value in this case. They differ based on whether FlagsAttribute is applied to it.


You can also get a array filled with either the value (GetValues) or names (GetNames) of all the constants in the enum.

string[] names = Enum.GetNames(typeof(Coolness));

int index = 0;

foreach (Coolness coolVal in Enum.GetValues(typeof(Coolness)))

{

Console.WriteLine(“{0,-10} => {1}”, names[index++],

coolVal.ToString(“D”));

}


This prints


NotSoCool  => 5
Cool       => 6
VeryCool   => 12
SuperCool  => 13


You can also query the name of the constant in the enum that has the specified value or whether a value is defined in the enum or not. The following will print cool and 5 is not defined.

Console.WriteLine(Enum.GetName(typeof(Coolness), 6));

if(!Enum.IsDefined(typeof(Coolness), (byte)7))

Console.WriteLine(“5 is Not Defined”);


Overriding ToString()


You cannot override the ToString of the enum type. So in case you wanted to display “Not so cool” instead of NotSoCool when someone called ToString on your enum type then you cannot do that simply by overriding the ToString.


This is a common issue that comes up frequently when you want to show values in reports, web pages, XML where you want to put in human readable text for enum values. Commonly people use non-generic solution of maintaining arrays of these descriptions and get text out of them by indexing using the enum value or some other things like storing it in a hashtable and using the ToString value as the key to get the desciption out.


A generic solution would be to apply custom attributes on the enum constants and write static methods to get the desciption. See the modified code below

using System;

using System.Reflection;

namespace FunWithEnum

{

enum Coolness : byte

{

[Description(“Not so cool”)]

NotSoCool = 5,

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

[Description(“Very cool”)]

VeryCool = NotSoCool + 7,

[Description(“Super cool”)]

SuperCool

}

class Description : Attribute

{

public string Text;

public Description(string text)

{

Text = text;

}

}

class Program

{

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(Description),
false
);

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

return ((Description)attrs[0]).Text;

}

return en.ToString();

}

static void Main(string[] args)

{

Coolness coolType1 = Coolness.Cool;

Coolness coolType2 = Coolness.NotSoCool;

Console.WriteLine(GetDescription(coolType1));

Console.WriteLine(GetDescription(coolType2));

}

}

}


Using this approach is pretty generic because for all enum constants that have this attribute applied to it, the desciption will be picked up from it and for those that do not have the attribute the common ToString() method will be called to get the description. However, the GetDescription uses reflection and can be slow.


The method shown above needs an explicit method call. If you prefer enum.GetDescription() then you need to use extension method as outlined here.

Comments (50)

  1. Anonymous says:

    As it turns out, there is already a DescriptionAttribute class within the System.ComponentModel namespace, so if all you need to assign to an Enum member is a simple description, you don’t even need a custom attribute class of your own and can use the built in DescriptionAttribute class instead.

    We’ve been using this approach for quite some time to map different (mostly meaningless) database codes and values to meaningful enums for quite some time and it has worked like a charm for us, makes the code much more readable.

    Regards, Robert

  2. Thanks for the pointer. I did not know about the DescriptionAttribute. The code gets even simpler with this!!!!

  3. Anonymous says:

    I like the attributes. In the past I have used a function that converts the enum strings to human strings. This code relies on the developer using good naming standards for the enum values. But if you can’t rely on that, you couldn’t rely on them to put in the attribute values either, so I call it a wash.

    I have another function that you can pass an enum type, and it will populate a drop down list from the enum, using the int value for the list values, and the text description (passed through this function) for the text value.

    public static string FixEnumString(string s)

    {

    string output = "";

    StringBuilder sb = new StringBuilder(s.Length);

    foreach (char c in s)

    {

    if (sb.Length != 0)

    {

    if (c.ToString()!=c.ToString().ToLower())

    sb.Append(" ");

    }

    sb.Append(c);

    }

    output = sb.ToString();

    output = output.Replace("I D", "ID");

    output = output.Replace("_"," ");

    output = output.Replace(" ", " ");

    //System.Web.HttpContext.Current.Response.Write(output + "<br>");

    return output;

    }

  4. Jason I do not agree that this is a wash. Reason being that with this approach there are two compeling advantages.

    1. You can use localized strings!!!

    2. You can enforce the developer to add the description string by introducing Debug.Assert in GetDescription function. Taking it to the extreme you can even throw an exception if you do not get the description

  5. Anonymous says:

    The solution is quite nice. But I am having a small issue. I want to get the corresponding enum depending upon the string. Say when I pass "Not so cool" string, I would like to get Coolness.NotSoCool. Any ideas

    Thanks

  6. This should be possible, however you need to iterate through all the types in the assebly and do something like

    foreach (Type type in assembly.GetTypes())

    {

    if(!type.IsEnum) continue;

    MemberInfo[] memInfo = type.GetMembers();

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

    {

    object[] attrs = memInfo[0].GetCustomAttributes(typeof(Description), false);

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

    {

    if (string.Equals((Description)attrs[0]).Text, descriptionText)

    return (type);

    }

    }

    }

  7. Anonymous says:

    Hi, I came across your blog through a search on Google on "C# enum Length". Is there a way in C# to find the number of items in an enum? Something like Coolness.Length returning 3.

    Thanks

    HC

  8. HC you can take a look into http://blogs.msdn.com/abhinaba/archive/2006/01/14/512656.aspx

    you can get the length by

    Enum.GetValues(typeof(Coolness)).Length

  9. Anonymous says:

    Hi. I’m from Brazil. Sorry for my bad english. Based on ideas from all here, I made the following code to bind a dropdownlist to an enum:

    *****************************

       protected void FillComboWithEnum(ref DropDownList combo, Type myEnum)

       {

           ListItem item;

           string [] names;

           

           combo.Items.Clear();

           names = Enum.GetNames(myEnum);

           for (int i = 0; i <= names.GetUpperBound(0); i++)

           {

               item = new ListItem();

               item.Text = GetDescription((Enum)Enum.Parse(myEnum, names[i]));

               item.Value = Convert.ToInt32(Enum.Parse(myEnum, names[i])).ToString();

               combo.Items.Add(item);

           }

       }

       public static string GetDescription(Enum value)

       {

           FieldInfo fi = value.GetType().GetField(value.ToString());

           DescriptionAttribute[] attributes =

                 (DescriptionAttribute[])fi.GetCustomAttributes(

                 typeof(DescriptionAttribute), false);

           return (attributes.Length > 0) ? attributes[0].Description : value.ToString();

       }

    **************

    To use, just do as follows:

    FillComboWithEnum(ref combo, typeof(ENUM_NAME));

    where ENUM_NAME is the name of your enumeration.

    Best Regards,

    Marco Alves.

  10. Anonymous says:

    Recently, I was asked by a colleague how to databind a combo box with enumeration descriptions, and have…

  11. Anonymous says:

    Note: This post is still being edited. The final version will be available soon.

    Recently, I was asked…

  12. Anonymous says:

    Note: This post is still being edited. The final version will be available soon.

    Recently, I was asked…

  13. Anonymous says:

    Recently, I was asked by a colleague how to databind a combo box with enumeration descriptions, and have

  14. Anonymous says:

    This is cool found via Google. One draw back is that the methods are tied to a specific enum type (CoolValue). If there was a way of making a Generic method that would return the data for any enum:

    <pre>

       public struct EnumHelper

       {

           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(Description), false);

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

                       return ((Description)attrs[0]).Text;

               }

               return en.ToString();

           }

           public static Collection<KeyValuePair<string, string>> GetList(Type enumType)

           {

               string[] names = Enum.GetNames(enumType);

               Array values = Enum.GetValues(enumType);

               Collection<KeyValuePair<string, string>> tempList = new Collection<KeyValuePair<string, string>>();

               for (int counter = 0; counter < names.GetLength(0); counter++)

               {

                   MemberInfo[] memInfo = enumType.GetMember(names[counter]);

                   string description = names[counter];

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

                   {

                       object[] attrs = memInfo[0].GetCustomAttributes(typeof(Description), false);

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

                           description = ((Description)attrs[0]).Text;

                   }

                   tempList.Add(new KeyValuePair<string, string>(values.GetValue(counter).ToString(), description));

               }

               return tempList;

           }

       }

    </pre>

    One further enhancement is test and validating that an enum type is being passed. Anyway this was my updates after toying around with this for an hour or two. Any how I can set a DataSource to a list. The columns are Key, Value. And if need be use those column names in the designer to show or hide the Key.

    <pre>

    uxCoolValueComboBox = EnumHelper.GetList(TypeOf(CoolValue))

    </pre>

  15. Anonymous says:

    I’ve done something similar using System.ComponentModel.DescriptionAttribute and extended EnumConverter to test for the presence of the attribute.

    This works fine on the property grid but web controls don’t seem to use type converters to get string representations of enum values.

    Does anyone have any ideas?

  16. Anonymous says:

    Thank you all very much for the sample code (by Guy). However I modified a little for WinForm ComboBox (2.0)

    public struct EnumHelper

    {

    public static List <KeyValuePair<string, string>> GetList(Type enumType)

    {

    string[] names = Enum.GetNames(enumType);
    
    Array values = Enum.GetValues(enumType);
    
    List &lt;KeyValuePair &lt;string, string&gt;&gt; tempList = new List &lt;KeyValuePair&lt;string, string&gt;&gt;();
    
    for (int counter = 0; counter &lt; names.GetLength(0); counter++)
    
    {
    
        MemberInfo[] memInfo = enumType.GetMember(names[counter]);
    
        string description = names[counter];
    
        if (memInfo != null &amp;&amp; memInfo.Length &gt; 0)
    
        {
    
            DescriptionAttribute[] attrs = (DescriptionAttribute[])memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
    
            if (attrs != null &amp;&amp; attrs.Length &gt; 0)
    
                description = attrs[0].Description;
    
        }
    
        tempList.Add(new KeyValuePair&lt;string, string&gt;(values.GetValue(counter).ToString(), description));
    
    }
    
    return tempList;
    

    }

    // Implementation side

    MyCombo.DataSource = EnumHelper.GetList(typeof(MyEnum));

    MyCombo.ValueMember = "Key";

    MyCombo.DisplayMember = "Value";

    Thanks again.

  17. Anonymous says:

    You Da Man! Loved the enum Description. Sweeeeet 🙂

  18. Anonymous says:

    &lt;to get all the values as an array see here &gt; Sometimes you need to do something in code and you

  19. Anonymous says:

    Great article.  Check out the EnumDescConverter class over at Codeproject.  I’ve used this one quite a few times — works great.

    <a href="http://www.codeproject.com/csharp/EnumDescConverter.asp">http://www.codeproject.com/csharp/EnumDescConverter.asp</a&gt;

  20. Anonymous says:

    Guess I clobbered the URL above. Whoops.

    http://www.codeproject.com/csharp/EnumDescConverter.asp

  21. Anonymous says:

    if one cannot override ToString please explain me how they do that

    using System;

    using System.IO;

    namespace test_console_application

    {

       class Program

       {

           public static void Main()

           {

               NotifyFilters filter = NotifyFilters.Attributes | NotifyFilters.Size;

               Console.WriteLine(filter);

           }

       }

    }

    Output: Attributes, Size

  22. Anonymous says:

    in case anyone cares I have found the answer to my question:

    in order to achieve the above you have to apply the attribute [Flags] to the enum declaration

  23. Alex Brown says:

    Here is an example of how you can use a generic class to make a wrapper around any enum.

    LocalizedEnumDescription.Description is implemented using the attribute method described above.

    When you put your enum into the combobox, you wrap in an EnumHolder. This seems to work pretty well.

       public class EnumHolder<T>

       {

           public readonly T Value;

           public EnumHolder( T enumValue)

           {

               Value = enumValue;

           }

           public override string ToString()

           {

               return LocalizedEnumDescription.Description(Value as System.Enum );

           }

       }

  24. coeamyd says:

    Just for completeness sake: If you need the enum string in XML serialization, there is another attribute for that, which the XmlSerializer takes into account.

    public enum MyValues

    {

       [System.Xml.Serialization.XmlEnumAttribute("Value one")]

       Value1,

       [System.Xml.Serialization.XmlEnumAttribute("Value two")]

       Value2,

       …

    }

    When using WCF, you should use the EnumMemberAttribute:

    public enum MyValues

    {

       [System.Runtime.Serialization.EnumMemberAttribute(Value = "Value one")]

       Value1,

       [System.Runtime.Serialization.EnumMemberAttribute(Value = "Value two")]

       Value2,

       …

    }

    Of course, both can be applied at the same time, if neccessary.

  25. coeamyd says:

    Just for completeness sake: If you need the enum string in XML serialization, there is another attribute for that, which the XmlSerializer takes into account.

    public enum MyValues

    {

       [System.Xml.Serialization.XmlEnumAttribute("Value one")]

       Value1,

       [System.Xml.Serialization.XmlEnumAttribute("Value two")]

       Value2,

       …

    }

    When using WCF, you should use the EnumMemberAttribute:

    public enum MyValues

    {

       [System.Runtime.Serialization.EnumMemberAttribute(Value = "Value one")]

       Value1,

       [System.Runtime.Serialization.EnumMemberAttribute(Value = "Value two")]

       Value2,

       …

    }

    Of course, both can be applied at the same time, if neccessary.

  26. Muaddubby says:

    Here’s a solid implementation of a C# string enumerator that behaves exactly like a regular one. You might find it handy 🙂

    http://cookingwithcsharp.blogspot.com/2007/12/999-c-string-enumerator.html

    Happy new year!

  27. Only .NET says:

    Sometimes, you would like to assign string values to the fields in an enumeration. This might be very

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

  29. Serge says:

    How I can serialize enum into the view:

    <DaysOfWeek>

     <Sunday />

     <Tuesday />

     <Friday />

    </DaysOfWeek>

  30. Anders says:

    Very nice, just what i was looking for.

    and for even more simplicity i added an extentionmethod to enum so that i can use .ToDescription on any enum and get the description, no functions with passing variables needed.

    cheers.

  31. EdG says:

    For enum serialization in C# and C++, it’s

    [System.Xml.Serialization.XmlEnumAttribute(Name="Value one")]

    For VB, leave off the Name= part.

  32. Sban says:

    Thanks for the code for string enum. It really helped me. 🙂

    Cheers.

  33. glupsch says:

    Another similar approach involving explicit casts:

    <code>

    using System;

    using System.Reflection;

    enum Coolness : byte

    {

       [Description("Not so cool")]

       NotSoCool = 5,

       Cool,

       [Description("Very cool")]

       VeryCool = NotSoCool + 7,

       [Description("Super cool")]

       SuperCool

    }

    class Description : Attribute

    {

       public string Text;

       public Description(string text)

       {

           Text = text;

       }

       public static explicit operator Description(Enum en)

       {

           FieldInfo field = en.GetType().GetField(en.ToString());

           Description d = GetCustomAttribute(field, typeof(Description)) as Description;

           return d ?? new Description(en.ToString());

       }

    }

    class Program

    {

       static void Main(string[] args)

       {

           Coolness coolType1 = Coolness.Cool;

           Coolness coolType2 = Coolness.NotSoCool;

           Console.WriteLine(

               ((Description)coolType1).Text

           );

           Console.WriteLine(

               ((Description)coolType2).Text

           );

           Console.ReadLine();

       }

    }

    </code>

  34. Thanks to the ideas you provided, I was able to add functionality to NHibernate’s EnumStringType to allow transparent storage of complex enum descriptions in a database.  You can see my approach here.

    http://geekswithblogs.net/ResultantCode/archive/2008/09/11/enums-and-nhibernate–taking-the-logic-out-of-the.aspx

  35. Mefito says:

    Your solution is not correct because you are saying that overring ToString in title. GetDescripton is NOT overriding anything 🙂 just a function call , please correct it. You can use more suitable title because your solution is at different point.

  36. Rubio says:

    I suppose you could use extension methods as well.

    public static string GetDescription(this Coolness type)

    {

      // Do your thing

    }

  37. Mike says:

    The following method implements AsString() to all enums which behaves similarly to ToString() except it uses the Description attribute.

    In addition it implements a ParseEnum method that can parse based on the ToString() or the AsString() results.

    This method requires LINQ and uses Extension Methods.

    // The coolness enum with descriptions

    enum Coolness : byte

    {

    [Description("Not so cool")]

    NotSoCool = 5,

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

    [Description("Very cool")]

    VeryCool = NotSoCool + 7,

    [Description("Super cool")]

    SuperCool

    }

    // A class to add extension methods

    static class ExtensionMethods

    {

    // Adds an AsString() method to every enum which uses the built in DescriptionAttribute

    public static string AsString(this Enum enumValue)

    {

    FieldInfo fi = enumValue.GetType().GetField(enumValue.ToString());

    if (fi != null)

    {

    object[] attrs = fi.GetCustomAttributes(typeof(DescriptionAttribute), true);

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

    {

    return ((DescriptionAttribute)attrs[0]).Description;

    }

    }

    return enumValue.ToString();

    }

    // Adds a ParseEnum method to every enum that parses from the AsString

    // Since value types are also IComparable, IFormattable and IConvertible they will

    // get the same methods, but will throw an InvalidCastException if used.

    public static T ParseEnum<T>(this T enumValue, string value)

    where T : IComparable, IFormattable, IConvertible

    {

    if (!typeof(Enum).IsAssignableFrom(typeof(T)))

    {

    throw new InvalidCastException();

    }

    IEnumerable<T> values = from Enum o in Enum.GetValues(typeof(T))

    where o.AsString() == value select (T)((object)o);

    if (values.Count() == 1)

    {

    return values.ElementAt(0);

    }

    else

    {

    // try using ToString() instead

    values = from Enum o in Enum.GetValues(typeof(T))

    where o.ToString() == value select (T)((object)o);

    if (values.Count() == 1)

    {

    return values.ElementAt(0);

    }

    }

    throw new FormatException();

    }

    // Implements a TryParseEnum method on all enums using the ParseEnum method above.

    public static bool TryParseEnum<T>(this T enumValue, string value, out T result)

    where T : IComparable, IFormattable, IConvertible

    {

    try

    {

    result = enumValue.Parse(value);

    return true;

    }

    catch

    {

    result = default(T);

    return false;

    }

    }

    }

    class Program

    {

    static void Main(string[] args)

    {

    Coolness coolness;

    if (!Coolness.Cool.TryParse(args[0], out coolness))

    {

    IEnumerable<Coolness> cools = from Enum o in Enum.GetValues(typeof(Coolness))

    select (Coolness)o;

    Console.WriteLine("Acceptable values:");

    foreach (Coolness c in cools)

    {

    Console.WriteLine("t{0}", c.ToString());

    if (c.ToString() != c.AsString())

    {

    Console.WriteLine("t{0}", c.AsString());

    }

    }

    }

    Console.WriteLine("{0} is {1}/{2}", args[0], coolness.ToString(), coolness.AsString());

    }

    }

  38. Evgeniy says:

    I have another solution without using attributes. This is the helper class which stores Dictionary<String, YourEnumeration> inside.

  39. Evgeniy says:

    It requres neither extension methods (.NET 3.0+ only) nor metadata analysis. Look at the ee.codeplex.com

  40. Patrick says:

    Mavarick asked:

    "The solution is quite nice. But I am having a small issue. I want to get the corresponding enum depending upon the string. Say when I pass "Not so cool" string, I would like to get Coolness.NotSoCool. Any ideas "

    You can use Enum.Parse for this.

    Example:

    public enum MyEnum

    {

    One,

    Two,

    Three

    }

    public static class MyEnums

    {

      public static MyEnum GetEnume(string str)

      {

         return (MyEnum) Enum.Parse(typeof(MyEnum), str);

      }

    }

  41. I came up with a cool solution. You can check it out here: http://robertbouillon.com/2010/04/23/localizing-enumerations-in-net/

    public enum UserStatus

    {

     [Description("Enabled")]

     Enabled,

     [Description("Disabled")]

     Disabled,

     [Description("Locked Out")]

     LockedOut

    }

    public void ShowUserStatus(UserStatus status)

    {

     MessageBox.Show(String.Format("User Status: {0}",status.ToUserString()));

    }

  42. An extension method makes this even easier:

       public static class EnumUtils {

           public static string GetDescription(this Enum en) {

               try {

                   MemberInfo[] info = en.GetType().GetMember(en.ToString());

                   if (info != null && info.Length > 0) {

                       object[] attrs = info[0].GetCustomAttributes(typeof(DescriptionAttribute), false);

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

                           return ((DescriptionAttribute)attrs[0]).Description;

                   }

               } catch (Exception) { } // Just in case.

               return en.ToString();

           }

       }

    Now, as long as EnumUtils is in your "using" then you can just simply do "myEnumVal.GetDescription()"

    If you want to localise then it's simple, use a new attribute that allows for a locale param, so you could define your enum as:

    enum MyEnum {

       [Description("Home")]

       [LocalisedDescription(Description="Startseite", Locale="de-DE")]

       Home,

    }

    and change the extension method to the following which will work for both localised attributes and a non-localised attribute:

       public static string GetDescription(this Enum en) {

           try {

               MemberInfo[] info = en.GetType().GetMember(en.ToString());

               if (info != null && info.Length > 0) {

                   object[] attrs = info[0].GetCustomAttributes(typeof(DescriptionAttribute), false);

                   if (attrs != null && attrs.Length > 0) {

                       if (attrs.Length > 1) {

                           DescriptionAttribute dflt = null;

                           foreach (DescriptionAttribute attr in attrs) {

                               LocalizedDescriptionAttribute la = attr as LocalizedDescriptionAttribute;

                               if (la != null && String.Equals(la.LocaleName, Thread.CurrentThread.CurrentCulture.Name)) {

                                   return la.Description;

                               }

                               if (la == null || String.Empty.Equals(la.LocaleName)) {

                                   dflt = attr;

                               }

                           }

                           if (dflt != null) {

                               return dflt.Description;

                           }

                       } else if (attrs.Length == 1) {

                           return ((DescriptionAttribute)attrs[0]).Description;

                       }

                   }

               }

           } catch (Exception) { }

           return en.ToString();

       }

    and finally, create your attribute class:

       public class LocalizedDescriptionAttribute : DescriptionAttribute {

           public LocalizedDescriptionAttribute() : base() { }

           public LocalizedDescriptionAttribute(string description) : base(description) { }

           public LocalizedDescriptionAttribute(string description, string localeName) : base(description) {

               this.LocaleName = localeName;

           }

           public string LocaleName {

               get;

               private set;

           }

       }

  43. Matt DiTrolio says:

    Thank you so much for this article, and to Robert Seso for mentioning the built-in attribute!

  44. Sunstar says:

    Come on guyes … Have any of you ever heard the word: Extentions.

    Istead if creating static funtions and so on, Just ad an extention to your code. Eighter in an extention DLL or just in the namespace…

    Extention:

    public static string GetDescription(this Enum e)  { return ""; /*Replace with. Convertion code*/ }

    Then you can just make a:

    enum A { [Description("a, a, a")] a_a_a }

    some Func{

    A var = a_a_a;

    Console.WriteLine(a_a_a.GetDescription());

    }

  45. Erwin says:

    You can just use the DescriptionAttribute without a custom class, just add

           static string GetDescription(Enum en)

           {

               var memInfo = en.GetType().GetMember(en.ToString());

               if (memInfo.Length <= 0) return en.ToString();

               var attrs = memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute),false);

               return attrs.Length > 0 ? ((DescriptionAttribute)attrs[0]).Description : en.ToString();

           }

    And nothing else 🙂