Enum With String Values In C#

Hello again,
 

I am currently making a Virtual Earth asp.net ajax server control and came to the point where I had to replicate the enums in my classes, but the issue with them is that the enums do not use integer values but string ones. In C# you cannot have an enum that has string values :(. So the solution I came up with (I am sure it has been done before) was just to make a new custom attribute called StringValueAttribute and use this to give values in my enum a string based value.

Note: All code here was written using .NET 3.5 and I am using 3.5 specific features like automatic properties and exension methods, this could be rewritten to suit 2.0 quite easily.


First I created the new custom attribute class, the source is below:

    /// <summary>
    /// This attribute is used to represent a string value
    /// for a value in an enum.
    /// </summary>
    public class StringValueAttribute : Attribute {

        #region Properties

        /// <summary>
        /// Holds the stringvalue for a value in an enum.
        /// </summary>
        public string StringValue { get; protected set; }

        #endregion

        #region Constructor

        /// <summary>
        /// Constructor used to init a StringValue Attribute
        /// </summary>
        /// <param name="value"></param>
        public StringValueAttribute(string value) {
            this.StringValue = value;
        }

        #endregion

    }

 
Then I created a new Extension Method which I will use to get the string value for an enums value:

        /// <summary>
        /// Will get the string value for a given enums value, this will
        /// only work if you assign the StringValue attribute to
        /// the items in your enum.
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string GetStringValue(this Enum value) {
            // Get the type
            Type type = value.GetType();

            // Get fieldinfo for this type
            FieldInfo fieldInfo = type.GetField(value.ToString());

            // Get the stringvalue attributes
            StringValueAttribute[] attribs = fieldInfo.GetCustomAttributes(
                typeof(StringValueAttribute), false) as StringValueAttribute[];

            // Return the first if there was a match.
            return attribs.Length > 0 ? attribs[0].StringValue : null;
        }
 

So now create your enum and add the StringValue attributes to your values:

 public enum Test : int {
        [StringValue("a")]
        Foo = 1,
        [StringValue("b")]
        Something = 2       
 }


Now you are ready to go, to get the string value for a value in the enum you can do so like this now:

Test t = Test.Foo;
string val = t.GetStringValue();

- or even -

string val = Test.Foo.GetStringValue();



All this is very easy to implement and I like the ease of use you get from the extension method [I really like them :)] and it gave me the power I needed to do what I needed. I haven't tested the performance hit that the reflection may give and might do so sometime soon.


Thanks
Stefan

Published Wednesday, March 12, 2008 11:56 PM by stefan.sedich

Comments

# re: Enum With String Values In C#

Thursday, March 13, 2008 4:49 AM by Vimpyboy

You can use this attribute for your StringValueAttribute:

[AttributeUsage(AttributeTargets.Field)]

If you have that, you can only use the attribute on the fields in an enum. :-)

# re: Enum With String Values In C#

Thursday, March 13, 2008 7:49 AM by stefan.sedich

Thanks for that mate, could be handy to stop people using it for purposes it is not made to do :P and I am sure it will happen.

Thanks

Stefan

# re: Enum With String Values In C#

Thursday, May 29, 2008 10:33 AM by James Coe

Hi Stefan,

Interesting approach to this. I also faced the same problem a while ago and posted my solution called SpecializedEnum to CodePlex recently. It provides fairly thorough emulation of enum's behaviors with any arbitrary object type.

James.

# re: Enum With String Values In C#

Thursday, June 26, 2008 2:36 PM by Ian

I like this idea.  I do have one question though.  How do you do the reverse?  Using your example, if you load the field from a database, and the field contains "b", how do you set the object property (which is of type Test) to the proper enum value?  In other words, how would you implement the extension method SetValueByString?  I ask because I've tried to do this and have failed so far :(

# re: Enum With String Values In C#

Tuesday, July 8, 2008 8:10 AM by Ian

How do you set the string value?  Ie you read the value "b" from the database and want to set the enum to that value.

# re: Enum With String Values In C#

Friday, August 1, 2008 3:31 AM by Jackkill

Unfortunately you can't use this where a constant value is expected, such as switch statements. So it kind of breaks the contract an Enum would normally have with its consumers.

# re: Enum With String Values In C#

Thursday, August 7, 2008 8:28 AM by stefan.sedich

Tarek,

I did not take this from anywhere? I just looked at that article and it is honestly the first time I have seen this.

I can see why you think I took this it is the same solution to the problem. But it is possible that 2 people out of 6,602,224,175 in the world could came up with the same idea, and implement it?

Fair enough if I did but I can assure you this was an idea that I had to solve a problem I had. I did not go and look for anything as I wanted to solve this issue myself and come up with a solution. If you think otherwise then you are open to your oppinion.

Cheers

Stefan

# re: Enum With String Values In C#

Monday, August 11, 2008 7:18 AM by Tarek

Stefan, I'm sorry for what I thought.

actually when i was browsing Google results for the c# string enum i got ur link as well codeproject one.

Thanks for the solution it saved me so much time. and thank u for sharing it with us it is really a genius idea.

Tarek Jajeh

# re: Enum With String Values In C#

Tuesday, August 12, 2008 2:26 AM by stefan.sedich

Tarek,

I can see where you were coming from. They look like the same solution. I am amazed myself. It is just something I thought of and did, and it turns out it had already been done, shoulda googled and saved myself the trouble :P but its good to solve things yourself sometimes.

Cheers

Stefan

# re: Enum With String Values In C#

Friday, September 26, 2008 3:37 AM by Alex

Why not using ToString/Parse methods of standard C# enum?

# re: Enum With String Values In C#

Sunday, September 28, 2008 4:31 AM by stefan.sedich

How would you propose this working to solve this issue?

# re: Enum With String Values In C#

Wednesday, October 22, 2008 2:54 AM by stefan.sedich

Valid points, but it is called StringValue which is pretty specific to what it does, and if you read the post I state the following:

"I am currently making a Virtual Earth asp.net ajax server control and came to the point where I had to replicate the enums in my classes, but the issue with them is that the enums do not use integer values but string ones. "

The reason for this is that the Virtual Earth library at the time of creating this has string based values for it's enumerations I needed a way to make nice enumerations that could also contain the string based value, this did this for me.

Thanks

Stefan

# re: Enum With String Values In C#

Friday, November 14, 2008 11:55 AM by Britton

what "using" statments are required for this code to work? I can't seem to compile it (all I have is one line at the top "using System;")

# re: Enum With String Values In C#

Saturday, November 15, 2008 8:42 AM by stefan.sedich

using System.Reflection will be needed as well. I would suggest you try Resharper (www.jetbrains.com/resharper) a tool like this will make life easy as it will help you add the required using statements for example, saving headache and time :)

Cheers

Stefan

# re: Enum With String Values In C#

Tuesday, November 18, 2008 12:36 PM by Brent

I had a similar situation where I needed to loop though a string array of property names in my object, in this case they were DateTime properties and did it the following way.  I used this as a helper method to build my insert sql and not include those properties with a null date.  The important part is inside the loop

       private string[] getNullableDateColumnsAndValues()

       {

           string columns = "AGENT_EFF_DT,AGENT_TERM_DT,AGENT_1ST_APPT_DT,BANK_DT,SELECT_START_DT,SELECT_END_DT,MUTUAL_DT,REGCD_DT,JUMBOCD_DT,TRANS_DT";

           string[] tmpArray = columns.Split(',');

           string buildColumnValues = string.Empty;

           string buildColumns = string.Empty;

           string[] returnArray = new string[2];

           Type type = this.GetType();

           foreach (string tmpStr in tmpArray)

           {

               DateTime dtProperty = (DateTime)type.InvokeMember(tmpStr, BindingFlags.GetProperty, null, this, null);

               if (dtProperty.Year != 1)

               {

                   buildColumnValues += "'" + dtProperty.ToString("d") + "',";

                   buildColumns += tmpStr + ",";

               }

           }

           //remove end comma

           if (!buildColumns.Equals(string.Empty))

           {

               buildColumnValues = buildColumnValues.Remove(buildColumnValues.Length - 1);

               buildColumns = buildColumns.Remove(buildColumns.Length - 1);

           }

           returnArray[0] = buildColumnValues;

           returnArray[1] = buildColumns;

           return returnArray;

       }

# re: Enum With String Values In C#

Wednesday, November 19, 2008 1:52 PM by marcdroo

Something similar that I've used - a little more code but no reflection performance hit:

enum BookingStatus {

       Attended = 0,

       Partial = 1,

       NoShow = 2,

       TurnedAway = 3,

       Failed = 4,

       OnlineTurnedAway = 5

   }

   static Dictionary<BookingStatus, string> BookingStatusNames = new Dictionary<BookingStatus, string>(){

       { BookingStatus.Attended  , "Attended" },  

       { BookingStatus.Partial , "Partial Attended" },  

       { BookingStatus.NoShow ,  "No Show" },  

       { BookingStatus.TurnedAway , "Turned Away Late" },  

       { BookingStatus.Failed , "Failed Test" },

       { BookingStatus.OnlineTurnedAway  ,"Online - Not Complete" }  

   };

# re: Enum With String Values In C#

Friday, November 21, 2008 8:27 AM by Ben Ellis

Thanks for this very interesting and useful. I made one ammendment to your code which is support for multiple values being set on a enum (i.e. when using the [Flags] Attribute).

This allows for multi-value / flag enums to be used.

# re: Enum With String Values In C#

Tuesday, January 13, 2009 7:06 PM by Pat Kujawa

For my use, it was easier to do the following (described in my URL):

using System;

using System.Collections.Generic;

namespace testConsole

{

   class Program

   {

       static void Main(string[] args)

       {

           string[] stringArr = new string[] { "1", "2", "Text with spaces" };

           string text1;

           string text2;

           string text3;

           IEnumerator<string> stringEnum = Program.makeStringEnum(stringArr);

           stringEnum.MoveNext();

           text1 = stringEnum.Current; stringEnum.MoveNext();

           text2 = stringEnum.Current; stringEnum.MoveNext();

           text3 = stringEnum.Current; stringEnum.MoveNext();

       }

       static IEnumerator<string> makeStringEnum(string[] arr)

       {

           foreach (string str in arr)

           {

               yield return str;

           }

       }

   }

}

# re: Enum With String Values In C#

Monday, January 19, 2009 3:22 PM by dotnet WorkerBee

Why do you inherit from "int"?  It works fine without.  Thanks and great implementation.

# re: Enum With String Values In C#

Thursday, January 22, 2009 11:10 AM by SiBorg

Why don't you just add a Description attribute (using System.ComponentModel) and a write a utility method to read? Very simple.

Write your enum as follows:

public enum AppStatus

{

[Description("Nothing in here")]

None = 0,

[Description("Out of scope")]

OutOfScope,

[Description("Oops something went wrong")]

SomethingWentWrong,

[Description("We have no idea")]

NoIdea,

[Description("Working normally")]

WorkingAsNormal,

}

Then a simple util method to read them using reflection.

public static String GetEnumDescription(Enum e)

{

FieldInfo fieldInfo = e.GetType().GetField(e.ToString());

DescriptionAttribute[] enumAttributes = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);

if (enumAttributes.Length > 0)

{

return enumAttributes[0].Description;

}

return e.ToString();

}

AppStatus myAppStatus = AppStatus.WorkingAsNormal;

string myAppStatusDescription = GetEnumDescription(myAppStatus);

# re: Enum With String Values In C#

Friday, February 13, 2009 1:04 PM by Klaus Veber

Enum.GetName( typeof(Patology), enumPatology)

# re: Enum With String Values In C#

Saturday, February 14, 2009 3:30 AM by Francesc Ramos

Thanks, this is perfect for me

# re: Enum With String Values In C#

Friday, April 3, 2009 9:55 AM by Marceli

Hi,

it's exactly what I've looking for  :)

How to do it reverse?

When I receive string :

public MyEnum Choos

{

get

{

string Value = CallCallback();

return ?????? HOW TO PARSE IT

}

}

enum MyEnum{

[StringValue("ok: none")]

None = 0,

[StringValue("You're switching to partial block!")]

Partial = 1,

[StringValue("The system is hidden. Leave it !")]

Hidden = 2,

[StringValue("smth4")]

Closed = 3,

[StringValue("smth 6")]

Failed = 4,

[StringValue("smth 5")]

isOpen = 5

}

# re: Enum With String Values In C#

Wednesday, April 29, 2009 9:25 AM by npiaseck

Easy, simple, clean. Thanks for posting this.

# re: Enum With String Values In C#

Monday, June 29, 2009 2:47 AM by Kinjal Shah

Thanks for share this one.

Its awesome.

Once again thanks

# re: Enum With String Values In C#

Thursday, July 23, 2009 3:56 AM by louie

any performance issue here? when i use the GetstringValue

# re: Enum With String Values In C#

Thursday, July 23, 2009 10:52 AM by ManasMSDN

Thanks alot!   it helped me alot.

please keep posting like these kind of stuff.

# re: Enum With String Values In C#

Thursday, August 13, 2009 4:23 PM by Chad

So did anyone ever come up with a way to set the enum value from the string value returned from the database?

# re: Enum With String Values In C#

Monday, September 21, 2009 3:44 PM by Milton

Ian, for reverse approach, I will try with the following.

In my requirements, I need that just for one enum, that why is not an extension approach, but it may help.

       public static Enumerations.Pages GetPageByUrl(string pageUrl)

       {

           pageUrl = pageUrl.Substring(pageUrl.LastIndexOf('/') + 1);

           foreach (Enumerations.Pages item in Enum.GetValues(typeof(Enumerations.Pages)))

           {

               FieldInfo fieldInfo = typeof(Enumerations.Pages).GetField(item.ToString());

               StringEnumValueAttribute[] attribs = fieldInfo.GetCustomAttributes(

                   typeof(StringEnumValueAttribute),

                   false) as StringEnumValueAttribute[];

               if (attribs.Length > 0 && attribs[0].Value.Contains(pageUrl))

                   return item;

           }

           return Enumerations.Pages._NotAvailable;

       }

HTH.

Milton Rodríguez

# re: Enum With String Values In C#

Thursday, September 24, 2009 3:23 PM by Davy

Stefan,

can I show the selected string attribute for the selected description based on the value similar to:

Enum.GetName(typeof(MyEnum), myId) would return the selected description for that id.

cheers

Davy

# re: Enum With String Values In C#

Friday, October 16, 2009 1:44 AM by om

Hi Its a very good article and exactly the same which I was looking for. Thanks a lot.

# re: Enum With String Values In C#

Thursday, October 22, 2009 12:08 AM by spike

Hey guys, how do I reversed the code above?

# re: Enum With String Values In C#

Friday, November 6, 2009 9:12 PM by Alex

Anyone run into to a compiler error: "Extension methods must be defined in a non-generic static class" on public class StringValueAttribute : Attribute section ?? (I'm using .net 3.5)

# re: Enum With String Values In C#

Tuesday, December 8, 2009 11:17 AM by k

Good one , helped me understand attributes much better than the MSDN documentation

# re: Enum With String Values In C#

Wednesday, January 6, 2010 4:00 PM by hugonne

Here's how you'll go the other way around (string to enum value):

public static object GetEnumStringValue(this string value,

Type enumType, bool ignoreCase)

{

object result = null;

string enumStringValue = null;

if (!tipoEnum.IsEnum)

throw new ArgumentException

("enumType should be a valid enum");

foreach (FieldInfo fieldInfo in enumType.GetFields())

{

var attribs =

fieldInfo.GetCustomAttributes(typeof(StringValueAttribute), false)

as StringValueAttribute[];

//Get the StringValueAttribute for each enum member

if (attribs.Length > 0)

enumStringValue = attribs[0].StringValue;

if (string.Compare(enumStringValue, value, ignoreCase) == 0)

result = Enum.Parse(enumType, fieldInfo.Name);

}

return result;

}