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!

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

Comments

Gravatar
# re: C#: Enums and String Values
Posted by Shouha
on 7/22/2008 4:06 AM
Very Nice Work Man I love it


Thank you alot.
Gravatar
# re: C#: Enums and String Values
Posted by jonathan parker
on 10/3/2008 3:54 PM
hey thanks for the great piece of code...it was really helpful for me today...
Gravatar
# re: C#: Enums and String Values
Posted by boy
on 10/27/2008 9:48 PM
Give a example,please!Thanks.
Gravatar
# re: C#: Enums and String Values
Posted by M.Efe Ozer
on 10/31/2008 10:09 AM
Thanks for posting, Vb.net version of codes i posted below

mefeozer.wordpress.com/.../get-enum-values-as-s...
Gravatar
# re: C#: Enums and String Values
Posted by Dirk Garner
on 12/9/2008 12:48 PM

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

Enum.Parse(enumType, name);


Thank you!
Gravatar
# re: C#: Enums and String Values
Posted by anjee
on 12/12/2008 1:38 PM
Thanks for sharing..helped me a lot.
Gravatar
# Help with EnumMemberAttribute? | keyongtech
on 1/18/2009 11:24 AM
Help with EnumMemberAttribute? | keyongtech
Gravatar
# re: C#: Enums and String Values
Posted by Bira
on 1/23/2009 11:56 AM
Very good post, the best solution I found to this problem!
Gravatar
# re: C#: Enums and String Values
Posted by a
on 2/11/2009 7:27 AM
very good
Gravatar
# re: C#: Enums and String Values
Posted by terry
on 4/30/2009 2:16 AM
cool
Gravatar
# re: C#: Enums and String Values
Posted by Tzadik
on 5/27/2009 9:45 AM
Why didn't you use Enum.GetValues instead of Enum.GetNames? Then you would have been able to avoid calling Enum.Parse later on.
Gravatar
# re: C#: Enums and String Values
on 9/10/2009 7:52 AM
Extremely cool. Thanx. I implemented a custom enum sorting routine based on attributes.
Gravatar
# re: C#: Enums and String Values
Posted by Joowa
on 10/26/2009 1:53 PM
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
Gravatar
# re: C#: Enums and String Values
Posted by Peter
on 11/30/2009 5:59 AM
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!
Gravatar
# re: C#: Enums and String Values
Posted by Kashif
on 1/28/2010 1:36 PM
Good job, it will be usefull to many people to be able to have typed string constants.
Gravatar
# re: C#: Enums and String Values
Posted by Steve
on 2/11/2010 6:15 PM
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'
Gravatar
# re: C#: Enums and String Values
Posted by Ananda
on 2/11/2010 7:59 PM
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
Gravatar
# re: C#: Enums and String Values
Posted by Werewolf
on 4/1/2010 2:27 PM
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");
Gravatar
# re: C#: Enums and String Values
Posted by satish
on 6/25/2010 2:59 AM
great dude. mast code aahe. Jay maharashtra
Gravatar
# re: C#: Enums and String Values
Posted by someone
on 7/1/2010 4:02 AM
Great post! I didn't really like how c# does it ,java wins in this area.
Gravatar
# re: C#: Enums and String Values
Posted by Waver
on 10/18/2010 3:15 PM
Unless I'm missing something, I don't think I agree with this approach. I think the reason Strings weren't included in enums for the Framework is because you wouldn't be able to use the [Flags] attribute. (You can't do bitwise operations on 'ChocolateChips' and 'Rocky Road'.

Enums are really just type-safe constants. If you really want strings, I would consider something like the following instead:


public class IceCream
{
public const string ChocolateChip = "Chocolate Chip";
public const string RockyRoad = "Rocky Road";
public const string Vanilla = "Vanilla";
}


You'll get intellisense and a level of safety by limiting your values to the values you put in the IceCream class.
Gravatar
# re: C#: Enums and String Values
Posted by Wayne
on 10/18/2010 3:41 PM
I disagree. Bitwise operations certainly can be applied. The whole point is that a String parameter can contain anything, whereas an enumeration constrains the domain of acceptable values.
Gravatar
# re: C#: Enums and String Values
Posted by Waver
on 10/19/2010 7:26 AM
Sorry. I guess I am missing something. I'm talking about using bitwise operations with the FlagsAttribute. For example,


[Flags]
public enum IceCream
{
ChocolateChip = 0,
RockyRoad = 1,
Vanilla = 2,
Strawberry = 4,
CherryGarcia = 8
}

IceCream iceCream = IceCream.RockyRoad | IceCream.CherryGarcia;


As you know, in this manner, I can indicate that my favorite Ice Cream is RockyRoad and CherryGarcia.

I don't see how I could do the same bitwise operations using strings. For example, the framework doesn't allow the following and would never work in the same manner:


[Flags]
public enum IceCream
{
ChocolateChip = "Chocolate Chip",
RockyRoad = "Rocky Road",
Vanilla = "Vanilla",
CherryGarcia = "Cherry Garcia"
}


Similarly, you could do bitwise operation on simple ints:


int a = 1;
int b = 8;
int c = a | b;
Console.WriteLine(c);


But you can't do that with strings:


string e = "Rocky Road";
string f = "Cherry Garcia";

string g = e | f; // ???
Console.WriteLine(g);


If the framework allowed the following, you'd be correct, and could perform bitwise operations:


[Flags]
public enum IceCream
{
"Chocolate Chip" = 0,
"Rocky Road" = 1,
"Vanilla" = 2,
"Strawberry" = 4,
"Cherry Garcia" = 8
}


However, you stated the "utter lack of string VALUE enumerations."


I somehow feel we might be in agreement if we were speaking in person, and I'm just missing what you're trying to communicate in writing. And I certainly agree with your usage of the 'DescriptionAttribute'. I've used it quite often. But because of the 'DescriptionAttribute', I've just never found the lack of string VALUE enumerations to be an issue and I just always assumed they kept enums numerical for bitwise operations.

Perhaps what I'm missing is just an issue of symantics?

Gravatar
# re: C#: Enums and String Values
Posted by Ben
on 3/14/2011 4:47 PM
Gravatar
# re: C#: Enums and String Values
Posted by Ghalib Ghniem
on 10/18/2011 6:36 AM
Great Job, Thank you
Gravatar
# re: C#: Enums and String Values
Posted by Max
on 12/14/2011 11:50 AM
I ve added the vb.net version of your code in a module in my project however when I'm declaring an Enum type, Visual Studio always recognize it as an Integer like a normal Enum datatype.

I've also added an explicit reference to "System.Runtime.Serialization.dll" but it still doesn't work.

this is the module:


Imports System.Runtime.Serialization
'Assembly: System.Runtime.Serialization (in System.Runtime.Serialization.dll)
'.NET Framework supported version: 4, 3.5, 3.0

Module modEnumUtility

''' <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
Gravatar
# re: C#: Enums and String Values
Posted by MKar
on 12/16/2011 9:00 AM
Thanks a lot... the article is very helpful in my case...

For those who were unable to use 'enumvalyeOf', try below,

// Get the enum value of the string
object xx = EnumUtils.enumValueOf(type, typeof(YourEnumName));
Gravatar
# re: C#: Enums and String Values
Posted by Le Quynh Nhu
on 1/14/2012 4:46 AM
Thank a lot !
Gravatar
# re: C#: Enums and String Values
Posted by Roland
on 1/20/2012 12:44 PM
Thanks for this, its still saving alot of headache over 3 years on.

Havent read all the comments but it worked a treat for me. R
Gravatar
# re: C#: Enums and String Values
Posted by shri
on 4/17/2012 12:20 PM
really awesome post !!
Post Comment
Title *
Name *
Email
Url
Comment *  
Please add 7 and 2 and type the answer here: