C#: Enums and String Values

One of the biggest things that I've had a problem with C# is its complete, utter lack of string value enumerations.  Enums provide strongly typed domain values that make programming easier to manage.  However, since you can't include characters like wildcards, spaces, etc., this means that making a human readable enum a nearly impossible task.  Until now.  This takes a little more heavy lifting than I come to expect with the .Net framework, but is a relatively easy fix for what you get in return.  This is broken into two parts:
  1. Create the String value for the enum.
  2. Get the value out.

First things first, how to create a string value enum.  To do this we need to import the System.Reflection and System.ComponentModel into the class and to create a new enum as follows:

public enum IceCream
{
        [DescriptionAttribute("Chocolate Chip")]ChocolateChip,
        [DescriptionAttribute("Rocky Road")]RockyRoad,
        Vanilla
}

As you can see we define the enum just like we normally do, except we take advantage of C#'s DescriptionAttribute class.   What this does is allows us to bind a string attribute to the enum which normally only accepts  numerical type data.  Unlike other methods to do this, we don't break the enum paradigm.  If I had my druthers I would have liked to inherit from the Enum class itself, but that's not possible.

So, now that we've created our enum, how do we retrieve that value?  Next we create another class as outlined below:

public class EnumUtils
{
        public static string stringValueOf(Enum value)
        {
            FieldInfo fi = value.GetType().GetField(value.ToString());
            DescriptionAttribute[] attributes = (DescriptionAttribute[]) fi.GetCustomAttributes( typeof(DescriptionAttribute), false);
            if (attributes.Length > 0)
            {
                return attributes[0].Description;
            }
            else
            {
                return value.ToString();
            }
        }

        public static object enumValueOf(string value, Type enumType)
        {
            string[] names = Enum.GetNames(enumType);
            foreach (string name in names)
            {
                if (stringValueOf((Enum)Enum.Parse(enumType, name)).Equals(value))
                {
                    return Enum.Parse(enumType, name);
                }
            }

            throw new ArgumentException("The string is not a description or value of the specified enum.");
        }
}

What we do in the first method is use reflection to access the DescriptionAttribute that we created when we constructed the enum.  If the enum value doesn't have a DescriptionAttribute associated with it, we return the ToString() value of the enum itslef.  That way, enums like 'Vanilla' get returned as "Vanilla" instead of null.

The second method enumValueOf address the need to go from the string value to the enum itself.  This uses the Enum static methods to compare the string value to the list of enum values.  While this particular could be further optimized with caching, this sets up a basic, but useful string value enumeration.

Enjoy!

Print | posted on Friday, October 05, 2007 7:32 PM

Comments on this post

# re: C#: Enums and String Values

Requesting Gravatar...
Very Nice Work Man I love it


Thank you alot.
Left by Shouha on Jul 22, 2008 4:06 AM

# re: C#: Enums and String Values

Requesting Gravatar...
hey thanks for the great piece of code...it was really helpful for me today...
Left by jonathan parker on Oct 03, 2008 3:54 PM

# re: C#: Enums and String Values

Requesting Gravatar...
Give a example,please!Thanks.
Left by boy on Oct 27, 2008 9:48 PM

# re: C#: Enums and String Values

Requesting Gravatar...
Thanks for posting, Vb.net version of codes i posted below

mefeozer.wordpress.com/.../get-enum-values-as-s...
Left by M.Efe Ozer on Oct 31, 2008 10:09 AM

# re: C#: Enums and String Values

Requesting Gravatar...

I looked all over the internet for a solution such as yours:

Enum.Parse(enumType, name);


Thank you!
Left by Dirk Garner on Dec 09, 2008 12:48 PM

# re: C#: Enums and String Values

Requesting Gravatar...
Thanks for sharing..helped me a lot.
Left by anjee on Dec 12, 2008 1:38 PM

# Help with EnumMemberAttribute? | keyongtech

Requesting Gravatar...
Help with EnumMemberAttribute? | keyongtech
Left by Pingback/TrackBack on Jan 18, 2009 11:24 AM

# re: C#: Enums and String Values

Requesting Gravatar...
Very good post, the best solution I found to this problem!
Left by Bira on Jan 23, 2009 11:56 AM

# re: C#: Enums and String Values

Requesting Gravatar...
very good
Left by a on Feb 11, 2009 7:27 AM

# re: C#: Enums and String Values

Requesting Gravatar...
cool
Left by terry on Apr 30, 2009 2:16 AM

# re: C#: Enums and String Values

Requesting Gravatar...
Why didn't you use Enum.GetValues instead of Enum.GetNames? Then you would have been able to avoid calling Enum.Parse later on.
Left by Tzadik on May 27, 2009 9:45 AM

# re: C#: Enums and String Values

Requesting Gravatar...
Extremely cool. Thanx. I implemented a custom enum sorting routine based on attributes.
Left by attribcoderfor theday on Sep 10, 2009 7:52 AM

# re: C#: Enums and String Values

Requesting Gravatar...
Thanks for your help but I have one question: how do you give the enumtype to the enumValueOf-method? I tried something like:

EnumUtils.enumValueOf("dossier",SubjectType);

(SubjectType is an enum made the way you described)

but this doesn't compile. I tried several things but didn't find it
Left by Joowa on Oct 26, 2009 1:53 PM

# re: C#: Enums and String Values

Requesting Gravatar...
This article gives the light in which we can observe the reality. this is very nice one and gives in depth information. thanks for this nice article Good post.....Valuable information for all.I will recommend my friends to read this for sure…
Left by Internet Backgammon Bonus on Nov 09, 2009 4:54 AM

# re: C#: Enums and String Values

Requesting Gravatar...
I used this to implement enum based error codes. I got the benefit of enums and and associated 3 string attributes with each code. Thanks heaps for posting this fantastic tip!
Left by Peter on Nov 30, 2009 5:59 AM

# re: C#: Enums and String Values

Requesting Gravatar...
Good Post.It's really helpful and interesting
Left by Agenzia Web Marketing on Dec 10, 2009 4:56 AM

# re: C#: Enums and String Values

Requesting Gravatar...
This is really nice and interesting blog.I m glad to know.
Left by Agenzia Web Marketing on Dec 10, 2009 5:36 AM

# re: C#: Enums and String Values

Requesting Gravatar...
Good job, it will be usefull to many people to be able to have typed string constants.
Left by Kashif on Jan 28, 2010 1:36 PM

# re: C#: Enums and String Values

Requesting Gravatar...
Hi, thanks a lot this is great.

However, I am having a problem with the util function to return the enum object when passing a string.

For example, with your IceCream enum above:
IceCream test = EnumUtils.enumValueOf("Rocky Road", IceCream);

I get the following 3 errors with that statement:

The best overloaded method match for 'test1.EnumUtils.enumValueOf(string, System.Type)' has some invalid arguments

Argument '2': cannot convert from 'test1.IceCream' to 'System.Type'

'test1.IceCream' is a 'type' but is used like a 'variable'
Left by Steve on Feb 11, 2010 6:15 PM

# re: C#: Enums and String Values

Requesting Gravatar...
Here is the VB.NET version of the code, modified to handle EnumMemberAtributes instead of DescriptionAttributes. I enhanced it to handle when some of the enum members do not have the EnumMemberAttribute specified for them.

''' <summary>
''' Returns the Enum member that is labelled with the System.Runtime.Serialization.EnumMemberAttribute, if one is attached to the enum member containing the value specified in the Value parameter, otherwise try to return the enum member with the same name as the value parameter.
''' </summary>
<System.Runtime.CompilerServices.Extension()> _
Public Function getEnumValue(ByVal enumType As System.Type, ByVal value As String) As Object
Dim names As String() = System.Enum.GetNames(enumType)
For Each name As String In names
If (getString(DirectCast(System.Enum.Parse(enumType, name), System.Enum))).Equals(value) Then
Return System.Enum.Parse(enumType, name)
End If
Next name
Throw New ArgumentException("The string is not an EnumMember or name of an enum member of the specified enum.")
End Function

''' <summary>
''' Return the Value from the System.Runtime.Serialization.EnumMemberAttribute, if one is attached to the enum member, otherwise return the ToString() value of the enum member.
''' </summary>
<System.Runtime.CompilerServices.Extension()> _
Public Function getString(ByVal value As System.Enum) As Object
Dim fi As Reflection.FieldInfo = value.GetType().GetField(value.ToString())
Dim attributes As System.Runtime.Serialization.EnumMemberAttribute() = DirectCast(fi.GetCustomAttributes(GetType(System.Runtime.Serialization.EnumMemberAttribute), False), System.Runtime.Serialization.EnumMemberAttribute())
'If the attribute specified Custom Attribute type is not attached to the enum member, then an array with one empty struct is returned, and the value is null.
If (attributes.Length > 0 AndAlso attributes(0).Value IsNot Nothing) Then
Return attributes(0).Value
Else
Return value.ToString()
End If
End Function
Left by Ananda on Feb 11, 2010 7:59 PM

# re: C#: Enums and String Values

Requesting Gravatar...
Thanks for the help, I was missing the cast to Enum in the equality check...

Here's my code using generics w/ C#:

/// <summary>
/// Helper class for <see cref="Enum"/>s.
/// </summary>
public static class EnumHelper
{
/// <summary>
/// Parses the specified value.
/// </summary>
/// <typeparam name="T">Base Type Enum</typeparam>
/// <param name="value">The value.</param>
/// <returns>The enum value matching the value provided.</returns>
public static T Parse<T>(string value)
{
return (T)Enum.Parse(typeof(T), value);
}

/// <summary>
/// Parses the specified description value.
/// </summary>
/// <typeparam name="T">Base Type Enum</typeparam>
/// <param name="value">The value.</param>
/// <returns>The enum value matching the decription provided; otherwise the first item in your enum if not found.</returns>
public static T ParseByDescription<T>(string value)
{
foreach (var name in Enum.GetNames(typeof(T)))
{
var enumValue = Parse<T>(name) as Enum;
if (enumValue.Description().Equals(value))
{
return Parse<T>(name);
}
}

return default(T);
}

/// <summary>
/// Returns the text value of the DescriptionAttribute for the given enum.
/// If no description attribute is found, the enum's .ToString() value is returned.
/// </summary>
/// <param name="enumeration">The enumeration.</param>
/// <returns>The value from the <see cref="DescriptionAttribute"/>. If not available then performs a ToString().</returns>
public static string Description(this Enum enumeration)
{
var value = enumeration.ToString();
var type = enumeration.GetType();
var descAttribute = (DescriptionAttribute[])type.GetField(value).GetCustomAttributes(typeof(DescriptionAttribute), false);
return descAttribute.Length > 0 ? descAttribute[0].Description : value;
}
}

Usage:
var myValue = EnumHelper.ParseByDescription<IceCream>("Rocky Road");
Left by Werewolf on Apr 01, 2010 2:27 PM

# re: C#: Enums and String Values

Requesting Gravatar...
This is my first time i visit here. I found so many interesting stuff in your blog. I guess I am not the only one having all the enjoyment here! keep up the good work.
Left by convert miles to km on May 21, 2010 4:40 AM

# re: C#: Enums and String Values

Requesting Gravatar...
great dude. mast code aahe. Jay maharashtra
Left by satish on Jun 25, 2010 2:59 AM

# re: C#: Enums and String Values

Requesting Gravatar...
Great post! I didn't really like how c# does it ,java wins in this area.
Left by someone on Jul 01, 2010 4:02 AM

Your comment:

 (will show your gravatar)
 
Please add 1 and 3 and type the answer here: