By user29964


2009-01-08 14:15:55 8 Comments

I have the following enumeration:

public enum AuthenticationMethod
{
    FORMS = 1,
    WINDOWSAUTHENTICATION = 2,
    SINGLESIGNON = 3
}

The problem however is that I need the word "FORMS" when I ask for AuthenticationMethod.FORMS and not the id 1.

I have found the following solution for this problem (link):

First I need to create a custom attribute called "StringValue":

public class StringValue : System.Attribute
{
    private readonly string _value;

    public StringValue(string value)
    {
        _value = value;
    }

    public string Value
    {
        get { return _value; }
    }

}

Then I can add this attribute to my enumerator:

public enum AuthenticationMethod
{
    [StringValue("FORMS")]
    FORMS = 1,
    [StringValue("WINDOWS")]
    WINDOWSAUTHENTICATION = 2,
    [StringValue("SSO")]
    SINGLESIGNON = 3
}

And of course I need something to retrieve that StringValue:

public static class StringEnum
{
    public static string GetStringValue(Enum value)
    {
        string output = null;
        Type type = value.GetType();

        //Check first in our cached results...

        //Look for our 'StringValueAttribute' 

        //in the field's custom attributes

        FieldInfo fi = type.GetField(value.ToString());
        StringValue[] attrs =
           fi.GetCustomAttributes(typeof(StringValue),
                                   false) as StringValue[];
        if (attrs.Length > 0)
        {
            output = attrs[0].Value;
        }

        return output;
    }
}

Good now I've got the tools to get a string value for an enumerator. I can then use it like this:

string valueOfAuthenticationMethod = StringEnum.GetStringValue(AuthenticationMethod.FORMS);

Okay now all of these work like a charm but I find it a whole lot of work. I was wondering if there is a better solution for this.

I also tried something with a dictionary and static properties but that wasn't better either.

30 comments

@Ramil Shavaleev 2019-07-04 12:22:33

You can declare enum and the dictionary in which the key will be the value of the enumeration. In the future, you can refer to the dictionary to get the value. Thus, it will be possible to pass parameters to functions as the type of enum, but to get the real value from the dictionary:

using System;
using System.Collections.Generic;

namespace console_test
{
    class Program
    {
        #region SaveFormat
        internal enum SaveFormat
        {
            DOCX,
            PDF
        }

        internal static Dictionary<SaveFormat,string> DictSaveFormat = new Dictionary<SaveFormat, string>
        {
            { SaveFormat.DOCX,"This is value for DOCX enum item" },
            { SaveFormat.PDF,"This is value for PDF enum item" }
        };

        internal static void enum_value_test(SaveFormat save_format)
        {
            Console.WriteLine(DictSaveFormat[save_format]);
        }
        #endregion

        internal static void Main(string[] args)
        {
            enum_value_test(SaveFormat.DOCX);//Output: This is value for DOCX enum item
            Console.Write("Press any key to continue . . . ");
            Console.ReadKey(true);
        }
    }
}

@Lockszmith 2011-12-02 07:43:50

Update: Visiting this page, 8 years later, after not touching C# for a long while, looks like my answer is no longer the best solution. I really like the converter solution tied with attribute-functions.

If you are reading this, please make sure you also check out other answers.
(hint: they are above this one)


As most of you, I really liked the selected answer by Jakub Šturc, but I also really hate to copy-paste code, and try to do it as little as I can.

So I decided I wanted an EnumBase class from which most of the functionality is inherited/built-in, leaving me to focus on the content instead of behavior.

The main problem with this approach is based on the fact that although Enum values are type-safe instances, the interaction is with the Static implementation of the Enum Class type. So with a little help of generics magic, I think I finally got the correct mix. Hope someone finds this as useful as I did.

I'll start with Jakub's example, but using inheritance and generics:

public sealed class AuthenticationMethod : EnumBase<AuthenticationMethod, int>
{
    public static readonly AuthenticationMethod FORMS =
        new AuthenticationMethod(1, "FORMS");
    public static readonly AuthenticationMethod WINDOWSAUTHENTICATION =
        new AuthenticationMethod(2, "WINDOWS");
    public static readonly AuthenticationMethod SINGLESIGNON =
        new AuthenticationMethod(3, "SSN");

    private AuthenticationMethod(int Value, String Name)
        : base( Value, Name ) { }
    public new static IEnumerable<AuthenticationMethod> All
    { get { return EnumBase<AuthenticationMethod, int>.All; } }
    public static explicit operator AuthenticationMethod(string str)
    { return Parse(str); }
}

And here is the base class:

using System;
using System.Collections.Generic;
using System.Linq; // for the .AsEnumerable() method call

// E is the derived type-safe-enum class
// - this allows all static members to be truly unique to the specific
//   derived class
public class EnumBase<E, T> where E: EnumBase<E, T>
{
    #region Instance code
    public T Value { get; private set; }
    public string Name { get; private set; }

    protected EnumBase(T EnumValue, string Name)
    {
        Value = EnumValue;
        this.Name = Name;
        mapping.Add(Name, this);
    }

    public override string ToString() { return Name; }
    #endregion

    #region Static tools
    static private readonly Dictionary<string, EnumBase<E, T>> mapping;
    static EnumBase() { mapping = new Dictionary<string, EnumBase<E, T>>(); }
    protected static E Parse(string name)
    {
        EnumBase<E, T> result;
        if (mapping.TryGetValue(name, out result))
        {
            return (E)result;
        }

        throw new InvalidCastException();
    }
    // This is protected to force the child class to expose it's own static
    // method.
    // By recreating this static method at the derived class, static
    // initialization will be explicit, promising the mapping dictionary
    // will never be empty when this method is called.
    protected static IEnumerable<E> All
    { get { return mapping.Values.AsEnumerable().Cast<E>(); } }
    #endregion
}

@Cory-G 2019-03-21 23:34:09

You may be able to call the derived static constructor from the base static constructor. I'm still looking into it, but so far I have found no issues with it: stackoverflow.com/questions/55290034/…

@Jahan 2019-04-10 09:14:24

Enum.GetName(typeof(MyEnum), (int)MyEnum.FORMS)
Enum.GetName(typeof(MyEnum), (int)MyEnum.WINDOWSAUTHENTICATION)
Enum.GetName(typeof(MyEnum), (int)MyEnum.SINGLESIGNON)

outputs are:

"FORMS"

"WINDOWSAUTHENTICATION"

"SINGLESIGNON"

@Pangamma 2018-09-06 17:35:42

For larger string enum sets, the listed examples can become tiresome. If you want a list of status codes, or a list of other string based enums, an attribute system is annoying to use, and a static class with instances of itself is annoying to configure. For my own solution, I make use of T4 templating to make it easier to have string-backed enums. The result comes out similar to how the HttpMethod class works.

You can use it like this:

    string statusCode = ResponseStatusCode.SUCCESS; // Automatically converts to string when needed
    ResponseStatusCode codeByValueOf = ResponseStatusCode.ValueOf(statusCode); // Returns null if not found

    // Implements TypeConverter so you can use it with string conversion methods.
    var converter = System.ComponentModel.TypeDescriptor.GetConverter(typeof(ResponseStatusCode));
    ResponseStatusCode code = (ResponseStatusCode) converter.ConvertFromInvariantString(statusCode);

    // You can get a full list of the values
    bool canIterateOverValues = ResponseStatusCode.Values.Any(); 

    // Comparisons are by value of the "Name" property. Not by memory pointer location.
    bool implementsByValueEqualsEqualsOperator = "SUCCESS" == ResponseStatusCode.SUCCESS; 

You start out with a Enum.tt file.

<#@ include file="StringEnum.ttinclude" #>


<#+
public static class Configuration
{
    public static readonly string Namespace = "YourName.Space";
    public static readonly string EnumName = "ResponseStatusCode";
    public static readonly bool IncludeComments = true;

    public static readonly object Nodes = new
    {
        SUCCESS = "The response was successful.",
        NON_SUCCESS = "The request was not successful.",
        RESOURCE_IS_DISCONTINUED = "The resource requested has been discontinued and can no longer be accessed."
    };
}
#>

Then, you add in your StringEnum.ttinclude file.

<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Reflection" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".cs" #>
<#@ CleanupBehavior processor="T4VSHost" CleanupAfterProcessingtemplate="true" #>

//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;

namespace <#= Configuration.Namespace #>
{
    /// <summary>
    /// TypeConverter implementations allow you to use features like string.ToNullable(T).
    /// </summary>
    public class <#= Configuration.EnumName #>TypeConverter : TypeConverter
    {
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
        }

        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
        {
            var casted = value as string;

            if (casted != null)
            {
                var result = <#= Configuration.EnumName #>.ValueOf(casted);
                if (result != null)
                {
                    return result;
                }
            }

            return base.ConvertFrom(context, culture, value);
        }

        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
        {
            var casted = value as <#= Configuration.EnumName #>;
            if (casted != null && destinationType == typeof(string))
            {
                return casted.ToString();
            }

            return base.ConvertTo(context, culture, value, destinationType);
        }
    }

    [TypeConverter(typeof(<#= Configuration.EnumName #>TypeConverter))]
    public class <#= Configuration.EnumName #> : IEquatable<<#= Configuration.EnumName #>>
    {
//---------------------------------------------------------------------------------------------------
// V A L U E S _ L I S T
//---------------------------------------------------------------------------------------------------
<# Write(Helpers.PrintEnumProperties(Configuration.Nodes)); #>

        private static List<<#= Configuration.EnumName #>> _list { get; set; } = null;
        public static List<<#= Configuration.EnumName #>> ToList()
        {
            if (_list == null)
            {
                _list = typeof(<#= Configuration.EnumName #>).GetFields().Where(x => x.IsStatic && x.IsPublic && x.FieldType == typeof(<#= Configuration.EnumName #>))
                    .Select(x => x.GetValue(null)).OfType<<#= Configuration.EnumName #>>().ToList();
            }

            return _list;
        }

        public static List<<#= Configuration.EnumName #>> Values()
        {
            return ToList();
        }

        /// <summary>
        /// Returns the enum value based on the matching Name of the enum. Case-insensitive search.
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static <#= Configuration.EnumName #> ValueOf(string key)
        {
            return ToList().FirstOrDefault(x => string.Compare(x.Name, key, true) == 0);
        }


//---------------------------------------------------------------------------------------------------
// I N S T A N C E _ D E F I N I T I O N
//---------------------------------------------------------------------------------------------------      
        public string Name { get; private set; }
        public string Description { get; private set; }
        public override string ToString() { return this.Name; }

        /// <summary>
        /// Implcitly converts to string.
        /// </summary>
        /// <param name="d"></param>
        public static implicit operator string(<#= Configuration.EnumName #> d)
        {
            return d.ToString();
        }

        /// <summary>
        /// Compares based on the == method. Handles nulls gracefully.
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static bool operator !=(<#= Configuration.EnumName #> a, <#= Configuration.EnumName #> b)
        {
            return !(a == b);
        }

        /// <summary>
        /// Compares based on the .Equals method. Handles nulls gracefully.
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static bool operator ==(<#= Configuration.EnumName #> a, <#= Configuration.EnumName #> b)
        {
            return a?.ToString() == b?.ToString();
        }

        /// <summary>
        /// Compares based on the .ToString() method
        /// </summary>
        /// <param name="o"></param>
        /// <returns></returns>
        public override bool Equals(object o)
        {
            return this.ToString() == o?.ToString();
        }

        /// <summary>
        /// Compares based on the .ToString() method
        /// </summary>
        /// <param name="other"></param>
        /// <returns></returns>
        public bool Equals(<#= Configuration.EnumName #> other)
        {
            return this.ToString() == other?.ToString();
        }

        /// <summary>
        /// Compares based on the .Name property
        /// </summary>
        /// <returns></returns>
        public override int GetHashCode()
        {
            return this.Name.GetHashCode();
        }
    }
}

<#+

public static class Helpers
{
        public static string PrintEnumProperties(object nodes)
        {
            string o = "";
            Type nodesTp = Configuration.Nodes.GetType();
            PropertyInfo[] props = nodesTp.GetProperties().OrderBy(p => p.Name).ToArray();

            for(int i = 0; i < props.Length; i++)
            {
                var prop = props[i];
                if (Configuration.IncludeComments)
                {
                    o += "\r\n\r\n";
                    o += "\r\n        ///<summary>";
                    o += "\r\n        /// "+Helpers.PrintPropertyValue(prop, Configuration.Nodes);
                    o += "\r\n        ///</summary>";
                }

                o += "\r\n        public static readonly "+Configuration.EnumName+" "+prop.Name+ " = new "+Configuration.EnumName+"(){ Name = \""+prop.Name+"\", Description = "+Helpers.PrintPropertyValue(prop, Configuration.Nodes)+ "};";
            }

            o += "\r\n\r\n";

            return o;
        }

        private static Dictionary<string, string> GetValuesMap()
        {
            Type nodesTp = Configuration.Nodes.GetType();
            PropertyInfo[] props= nodesTp.GetProperties();
            var dic = new Dictionary<string,string>();
            for(int i = 0; i < props.Length; i++)
            {
                var prop = nodesTp.GetProperties()[i];
                dic[prop.Name] = prop.GetValue(Configuration.Nodes).ToString();
            }
            return dic;
        }

        public static string PrintMasterValuesMap(object nodes)
        {
            Type nodesTp = Configuration.Nodes.GetType();
            PropertyInfo[] props= nodesTp.GetProperties();
            string o = "        private static readonly Dictionary<string, string> ValuesMap = new Dictionary<string, string>()\r\n        {";
            for(int i = 0; i < props.Length; i++)
            {
                var prop = nodesTp.GetProperties()[i];
                o += "\r\n            { \""+prop.Name+"\", "+(Helpers.PrintPropertyValue(prop,Configuration.Nodes)+" },");
            }
            o += ("\r\n        };\r\n");

            return o;
        }


        public static string PrintPropertyValue(PropertyInfo prop, object objInstance)
        {
            switch(prop.PropertyType.ToString()){
                case "System.Double":
                    return prop.GetValue(objInstance).ToString()+"D";
                case "System.Float":
                    return prop.GetValue(objInstance).ToString()+"F";
                case "System.Decimal":
                    return prop.GetValue(objInstance).ToString()+"M";
                case "System.Long":
                    return prop.GetValue(objInstance).ToString()+"L";
                case "System.Boolean":
                case "System.Int16":
                case "System.Int32":
                    return prop.GetValue(objInstance).ToString().ToLowerInvariant();
                case "System.String":
                    return "\""+prop.GetValue(objInstance)+"\"";
            }

            return prop.GetValue(objInstance).ToString();
        }

        public static string _ (int numSpaces)
        {
            string o = "";
            for(int i = 0; i < numSpaces; i++){
                o += " ";
            }

            return o;
        }
}
#>

Finally, you recompile your Enum.tt file and the output looks like this:

//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

using System;
using System.Linq;
using System.Collections.Generic;

namespace YourName.Space
{
    public class ResponseStatusCode
    {
//---------------------------------------------------------------------------------------------------
// V A L U E S _ L I S T 
//---------------------------------------------------------------------------------------------------



        ///<summary>
        /// "The response was successful."
        ///</summary>
        public static readonly ResponseStatusCode SUCCESS = new ResponseStatusCode(){ Name = "SUCCESS", Description = "The response was successful."};


        ///<summary>
        /// "The request was not successful."
        ///</summary>
        public static readonly ResponseStatusCode NON_SUCCESS = new ResponseStatusCode(){ Name = "NON_SUCCESS", Description = "The request was not successful."};


        ///<summary>
        /// "The resource requested has been discontinued and can no longer be accessed."
        ///</summary>
        public static readonly ResponseStatusCode RESOURCE_IS_DISCONTINUED = new ResponseStatusCode(){ Name = "RESOURCE_IS_DISCONTINUED", Description = "The resource requested has been discontinued and can no longer be accessed."};


        private static List<ResponseStatusCode> _list { get; set; } = null;
        public static List<ResponseStatusCode> ToList()
        {
            if (_list == null)
            {
                _list = typeof(ResponseStatusCode).GetFields().Where(x => x.IsStatic && x.IsPublic && x.FieldType == typeof(ResponseStatusCode))
                    .Select(x => x.GetValue(null)).OfType<ResponseStatusCode>().ToList();
            }

            return _list;
        }

        public static List<ResponseStatusCode> Values()
        {
            return ToList();
        }

        /// <summary>
        /// Returns the enum value based on the matching Name of the enum. Case-insensitive search.
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static ResponseStatusCode ValueOf(string key)
        {
            return ToList().FirstOrDefault(x => string.Compare(x.Name, key, true) == 0);
        }


//---------------------------------------------------------------------------------------------------
// I N S T A N C E _ D E F I N I T I O N 
//---------------------------------------------------------------------------------------------------       
        public string Name { get; set; }
        public string Description { get; set; }
        public override string ToString() { return this.Name; }

        /// <summary>
        /// Implcitly converts to string.
        /// </summary>
        /// <param name="d"></param>
        public static implicit operator string(ResponseStatusCode d)
        {
            return d.ToString();
        }

        /// <summary>
        /// Compares based on the == method. Handles nulls gracefully.
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static bool operator !=(ResponseStatusCode a, ResponseStatusCode b)
        {
            return !(a == b);
        }

        /// <summary>
        /// Compares based on the .Equals method. Handles nulls gracefully.
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static bool operator ==(ResponseStatusCode a, ResponseStatusCode b)
        {
            return a?.ToString() == b?.ToString();
        }

        /// <summary>
        /// Compares based on the .ToString() method
        /// </summary>
        /// <param name="o"></param>
        /// <returns></returns>
        public override bool Equals(object o)
        {
            return this.ToString() == o?.ToString();
        }

        /// <summary>
        /// Compares based on the .Name property
        /// </summary>
        /// <returns></returns>
        public override int GetHashCode()
        {
            return this.Name.GetHashCode();
        }
    }
}

@Abet 2018-03-29 06:44:02

I know pretty well that this question have already been answered and that the OP is already happy with the accepted answer. But I found most of the answers, including the accepted one, to be a little bit more complicated.

I have a project which gave me a situation like this and I was able to achieve it this way.

First, you have to consider the casing of your enum names:

public enum AuthenticationMethod
{
    Forms = 1,
    WindowsAuthentication = 2,
    SingleSignOn = 3
}

Then, have this extension:

using System.Text.RegularExpression;

public static class AnExtension
{
    public static string Name(this Enum value)
    {
        string strVal = value.ToString();
        try
        {
            return Regex.Replace(strVal, "([a-z])([A-Z])", "$1 $2");
        }
        catch
        {
        }
        return strVal;
    }
}

Through this you can turn your every enum name to its string representation with each word separated with a space. Ex:

AuthenticationMethod am = AuthenticationMethod.WindowsAuthentication;
MessageBox.Show(am.Name());

@Svek 2019-02-07 06:27:13

If you read the original question, he wants different mapping, such as SingleSignOn to become SSO. Your solution does not work.

@David C 2015-09-22 20:46:21

Very simple solution to this with .Net 4.0 and above. No other code is needed.

public enum MyStatus
{
    Active = 1,
    Archived = 2
}

To get the string about just use:

MyStatus.Active.ToString("f");

or

MyStatus.Archived.ToString("f");`

The value will be "Active" or "Archived".

To see the different string formats (the "f" from above) when calling Enum.ToString see this Enumeration Format Strings page

@Grinn 2012-03-22 13:12:24

If you've come here looking to implement a simple "Enum" but whose values are strings instead of ints, here is the simplest solution:

    public sealed class MetricValueList
    {
        public static readonly string Brand = "A4082457-D467-E111-98DC-0026B9010912";
        public static readonly string Name = "B5B5E167-D467-E111-98DC-0026B9010912";
    }

Implementation:

var someStringVariable = MetricValueList.Brand;

@AndyGeek 2013-04-22 17:35:19

It's probably better to make the variables consts instead of using static readonly.

@Kristian Williams 2017-08-24 10:46:59

consts are not good for publicly accessible classes, as they are baked in compile time, you cannot replace a third party DLL without recompiling your whole code with consts.The performance offset of consts vs static readonly is negligible.

@ILIA BROUDNO 2015-04-17 21:50:01

In your question you never said that you actually need the numeric value of the enum anywhere.

If you do not and just need an enum of type string (which is not an integral type so can not be a base of enum) here is a way:

    static class AuthenticationMethod
    {
        public static readonly string
            FORMS = "Forms",
            WINDOWSAUTHENTICATION = "WindowsAuthentication";
    }

you can use the same syntax as enum to reference it

if (bla == AuthenticationMethod.FORMS)

It will be a bit slower than with numeric values (comparing strings instead of numbers) but on the plus side it is not using reflection (slow) to access the string.

@Harry .Naeem 2017-04-26 11:09:26

This worked for me! (y)

@Ed N. 2017-08-01 14:33:50

if you use "const" instead of "static readonly" then you can use the values as case labels in a switch statement.

@Hammad Khan 2016-10-03 07:33:49

old post but...

The answer to this may actually be very simple. Use Enum.ToString() function

There are 6 overloads of this function, you can use Enum.Tostring("F") or Enum.ToString() to return the string value. No need to bother with anything else. Here is a working Demo

Note that this solution may not work for all compilers (this demo does not work as expected) but at least it works for the latest compiler.

@Keith 2009-01-08 14:20:28

Unfortunately reflection to get attributes on enums is quite slow:

See this question: Anyone know a quick way to get to custom attributes on an enum value?

The .ToString() is quite slow on enums too.

You can write extension methods for enums though:

public static string GetName( this MyEnum input ) {
    switch ( input ) {
        case MyEnum.WINDOWSAUTHENTICATION:
            return "Windows";
        //and so on
    }
}

This isn't great, but will be quick and not require the reflection for attributes or field name.


C#6 Update

If you can use C#6 then the new nameof operator works for enums, so nameof(MyEnum.WINDOWSAUTHENTICATION) will be converted to "WINDOWSAUTHENTICATION" at compile time, making it the quickest way to get enum names.

Note that this will convert the explicit enum to an inlined constant, so it doesn't work for enums that you have in a variable. So:

nameof(AuthenticationMethod.FORMS) == "FORMS"

But...

var myMethod = AuthenticationMethod.FORMS;
nameof(myMethod) == "myMethod"

@Jon Skeet 2009-01-08 14:38:39

You can fetch the attribute values once and put them in a Dictionary<MyEnum,string> to keep the declarative aspect.

@Keith 2009-01-08 16:04:29

Yeah that's what we ended up doing in an app with lots of enums when we found out that the reflection was the bottle-neck.

@Helge Klein 2010-11-23 22:22:38

Thanks Jon and Keith, I ended up using your Dictionary suggestion. Works great (and fast!).

@user919426 2015-02-12 13:22:20

@JonSkeet I know this is old. But how would one achieve this?

@Jon Skeet 2015-02-12 13:52:17

@user919426: Achieve want? Putting them in a dictionary? Just create a dictionary, ideally with a collection initializer... it's not clear what you're asking for.

@user919426 2015-02-12 16:45:14

Thanks for responding @JonSkeet Sorry, I meant to ask the actual implementation. How to "fetch once" without re-calling again. Will use your answer to figure the logic.

@JoeBrockhaus 2016-03-01 18:17:06

nameof() only works if you know the enum instance ahead of time. ie in var enumVal = MyEnum.Value; the value returned by nameof(enumVal) will be 'enumVal', not 'Value'. It's a compiler feature, not runtime.

@Keith 2016-03-02 08:13:26

@JoeBrockhaus yes, although there's no instance involved - nameof(MyEnum.Value) will become "Value" at compile time, there's no instance of MyEnum.

@JoeBrockhaus 2016-03-02 14:36:05

@Keith Not sure I follow - this question (and answer) is about getting the name of an instance of an enum. Someone could easily come here, read this answer, see mention of nameof() being 'the quickest way to get enum names' and use it thinking they'd get the desired results. I know your example doesn't show the instance, but maybe worth an edit to the answer to clarify.

@Keith 2016-03-02 14:40:44

@JoeBrockhaus all the examples in the question seem to be getting the name of an explicit enum, for instance (from the question) StringEnum.GetStringValue(AuthenticationMethod.FORMS) - in that context nameof(AuthenticationMethod.FORMS) is quicker. I was quite explicit in the answer that this was strictly a compile time optimisation, but I will add clarification.

@WHol 2015-09-28 09:33:15

If I'm understanding you correctly, you can simply use .ToString() to retrieve the name of the enum from the value (Assuming it's already cast as the Enum); If you had the naked int (lets say from a database or something) you can first cast it to the enum. Both methods below will get you the enum name.

AuthenticationMethod myCurrentSetting = AuthenticationMethod.FORMS;
Console.WriteLine(myCurrentSetting); // Prints: FORMS
string name = Enum.GetNames(typeof(AuthenticationMethod))[(int)myCurrentSetting-1];
Console.WriteLine(name); // Prints: FORMS

Keep in mind though, the second technique assumes you are using ints and your index is 1 based (not 0 based). The function GetNames also is quite heavy by comparison, you are generating a whole array each time it's called. As you can see in the first technique, .ToString() is actually called implicitly. Both of these are already mentioned in the answers of course, I'm just trying to clarify the differences between them.

@Steve Mitcham 2009-01-08 15:52:42

I use a combination of several of the suggestions above, combined with some caching. Now, I got the idea from some code that I found somewhere on the net, but I can neither remember where I got it or find it. So if anyone ever finds something that looks similar please comment with the attribution.

Anyway, the usage involves the type converters, so if you are binding to the UI it 'just works'. You can extended with Jakub's pattern for quick code lookup by initializing from the type converter into the static methods.

The base usage would look like this

[TypeConverter(typeof(CustomEnumTypeConverter<MyEnum>))]
public enum MyEnum
{
    // The custom type converter will use the description attribute
    [Description("A custom description")]
    ValueWithCustomDescription,

   // This will be exposed exactly.
   Exact
}

The code for the custom enum type converter follows:

public class CustomEnumTypeConverter<T> : EnumConverter
    where T : struct
{
    private static readonly Dictionary<T,string> s_toString = 
      new Dictionary<T, string>();

    private static readonly Dictionary<string, T> s_toValue = 
      new Dictionary<string, T>();

    private static bool s_isInitialized;

    static CustomEnumTypeConverter()
    {
        System.Diagnostics.Debug.Assert(typeof(T).IsEnum,
          "The custom enum class must be used with an enum type.");
    }

    public CustomEnumTypeConverter() : base(typeof(T))
    {
        if (!s_isInitialized)
        {
            Initialize();
            s_isInitialized = true;
        }
    }

    protected void Initialize()
    {
        foreach (T item in Enum.GetValues(typeof(T)))
        {
            string description = GetDescription(item);
            s_toString[item] = description;
            s_toValue[description] = item;
        }
    }

    private static string GetDescription(T optionValue)
    {
        var optionDescription = optionValue.ToString();
        var optionInfo = typeof(T).GetField(optionDescription);
        if (Attribute.IsDefined(optionInfo, typeof(DescriptionAttribute)))
        {
            var attribute = 
              (DescriptionAttribute)Attribute.
                 GetCustomAttribute(optionInfo, typeof(DescriptionAttribute));
            return attribute.Description;
        }
        return optionDescription;
    }

    public override object ConvertTo(ITypeDescriptorContext context, 
       System.Globalization.CultureInfo culture, 
       object value, Type destinationType)
    {
        var optionValue = (T)value;

        if (destinationType == typeof(string) && 
            s_toString.ContainsKey(optionValue))
        {
            return s_toString[optionValue];
        }

        return base.ConvertTo(context, culture, value, destinationType);
    }

    public override object ConvertFrom(ITypeDescriptorContext context, 
       System.Globalization.CultureInfo culture, object value)
    {
        var stringValue = value as string;

        if (!string.IsNullOrEmpty(stringValue) && s_toValue.ContainsKey(stringValue))
        {
            return s_toValue[stringValue];
        }

        return base.ConvertFrom(context, culture, value);
    }
}

}

@Jakub Šturc 2009-01-08 14:29:12

Try type-safe-enum pattern.

public sealed class AuthenticationMethod {

    private readonly String name;
    private readonly int value;

    public static readonly AuthenticationMethod FORMS = new AuthenticationMethod (1, "FORMS");
    public static readonly AuthenticationMethod WINDOWSAUTHENTICATION = new AuthenticationMethod (2, "WINDOWS");
    public static readonly AuthenticationMethod SINGLESIGNON = new AuthenticationMethod (3, "SSN");        

    private AuthenticationMethod(int value, String name){
        this.name = name;
        this.value = value;
    }

    public override String ToString(){
        return name;
    }

}

Update Explicit (or implicit) type conversion can be done by

  • adding static field with mapping

    private static readonly Dictionary<string, AuthenticationMethod> instance = new Dictionary<string,AuthenticationMethod>();
    
    • n.b. In order that the initialisation of the the "enum member" fields doesn't throw a NullReferenceException when calling the instance constructor, be sure to put the Dictionary field before the "enum member" fields in your class. This is because static field initialisers are called in declaration order, and before the static constructor, creating the weird and necessary but confusing situation that the instance constructor can be called before all static fields have been initialised, and before the static constructor is called.
  • filling this mapping in instance constructor

    instance[name] = this;
    
  • and adding user-defined type conversion operator

    public static explicit operator AuthenticationMethod(string str)
    {
        AuthenticationMethod result;
        if (instance.TryGetValue(str, out result))
            return result;
        else
            throw new InvalidCastException();
    }
    

@Ant 2010-02-25 09:18:44

It looks like an enum but it isn't an enum. I can imagine that causing some interesting problems if people start trying to compare AuthenticationMethods. You probably need to overload various equality operators too.

@Jakub Šturc 2010-02-26 09:24:43

@Ant: I don't have to. Since we have only one instance of each AuthenticationMethod the reference equality inherited from Object works fine.

@InvisibleBacon 2010-04-23 19:25:14

+1 I've used this solution before. Like a powerful enum. I imagine you cannot use this as values in a switch statement though can you? Also, the only time you would have to worry about the equality problem is if this was declared as a struct rather than a class.

@Jakub Šturc 2010-06-22 09:17:32

@InvisibleBacon: Right, switch isn't option in this case. However sometimes you can replace switch with polymorphism. See: sourcemaking.com/refactoring/…

@tyriker 2010-10-13 19:16:33

This is weird, and seems dangerous to me... What prevents this from happening: AuthenticationMethod a = new AuthenticationMethod(); var b = a.FORMS.SINGLESIGNON; since a.FORMS is itself an instance of AuthenticationMethod?

@Jakub Šturc 2010-10-14 06:56:24

@tyriker: Compiler does. The constructor is private so you cannot create new instance. Also static members are not accessible through instance.

@tyriker 2010-10-14 17:56:46

@Jakub Very interesting. I had to play with it to figure out how to use it, and realize its benefits. It's a public, non-static class, but can't be instantiated and you can only access its static members. Basically, it behaves like an enum. But the best part...the static members are typed of the class and not a generic string or int. It's a ... [wait for it] ... type safe enum! Thanks for helping me understand.

@Sedat Kapanoglu 2011-01-19 12:14:37

I see a problem when you want to mix this with external values (e.g. DB). You want to cast that to a strongly typed one but you can't. It's also not possible to write a loop that matches a string to a correct strongly-typed value. All you can do is series of ugly if else statements.

@Jakub Šturc 2011-01-19 13:14:26

@ssg: Sorry I don't see your point. You can implement explicit / implicit operators on AuthenticationMethod class if you really need them.

@Sedat Kapanoglu 2011-01-19 14:57:51

@Jakub: Say you have 20 names and you use the same names in DB. You read the record and you want to cast it to "enum" in the code. You need to map each and every string to the strongly typed equivalent by check with series of ifs. How does operator overloading help here?

@Jakub Šturc 2011-01-19 18:24:45

@ssg: I've updated sample. So now if you can write var stronglyTypeInstance = (AuthenticationMethod)"FORMS"; I am not sure about conversion operators. Maybe static Parse method would work better. If you want it you can get it.

@pb. 2011-10-14 10:14:33

For further details on how to implement this pattern, take a look at javacamp.org/designPattern/enum.html I know it's not a C# implementation, but still understandable.

@Chris Moschini 2012-02-15 21:09:33

Love this solution - the only major downside I've hit with it is that it doesn't work in a switch statement - that is, I can use a normal enum or a list of const's in a switch, but not these.

@Mauricio Scheffer 2012-05-29 14:05:53

Er... This is just a degenerate disjoint union or discriminated union or tagged union en.wikipedia.org/wiki/Tagged_union . It's been around since the 1960's guys. No need to invent a flashy pattern name for something that has been around for decades and already has a perfectly suited name (which comes from math).

@Jakub Šturc 2012-05-29 18:44:39

@MauricioScheffer: I can argue about degeneration but you are right. All this has happened before and all this will happen again.

@Mauricio Scheffer 2012-05-29 22:38:15

I apologize for the patronizing tone in my previous comment. Absolutely out of place. It's just a synonym...

@Charles Bretana 2012-06-11 12:19:40

one change I'd make to this is to not store the string values as instance fields, but as static consts. Why waste the storage? Just put a switch case statement in the ToString(); then the string values are only stored in the type definition and not in each instance of the "enum." (the type). You could even just hard-code them in the case statements of the switch. Also, this is a prime example of a situation wheere you should use a struct instead of a class. It is, (or should be) basically immutable.

@Robert Koritnik 2012-06-19 11:36:43

@CharlesBretana: Are you talking about private static readonly Dictionary<string, AuthenticationMethod> instance variable? And please elaborate on the struct. I'm not sure if you can make it this ingenious...

@anaximander 2013-02-22 15:00:05

What I like about this is that you can also define extra methods on the enum, to give things like grouping behaviour (like the standard example of a DayOfTheWeek enumeration with a method IsWeekend that returns true if the instance being referenced is Saturday or Sunday).

@Derrick 2013-03-22 19:01:52

Those concerned with confusing later coders... One thing you can do is use the word "Enum" in the class name to entice user programmers to view the source code, if available.

@ashes999 2013-05-17 01:16:00

How would you persist this to/from a database?

@sparebytes 2013-08-13 16:17:47

This is a nice pattern but I have issues dealing with serialization... To implement ISerializable, your class must include a special constructor, which would break the sealed/singleton nature of the code. I'm also trying to use this TypeSafeEnum on a UserControl property - like this <uc:MyUC AuthMethod="FORMS" /> - so I had to implement a TypeConverter and that seems to be causing a slew of other problems - one of them being that the static constructor doesn't get ran before the TypeConverter attempts doing conversions. (Workaround: just store the prop as a string and cast when needed)

@kiran 2013-12-09 15:00:24

Too bad this wont work with Switch case statement as constants are only allowed as case

@deadlydog 2014-01-20 21:15:53

@kiran I've posted a slightly modified version of Jakub Šturc's answer below that allows it to be used with Switch-Case statements, so now there is no downside to this approach :)

@mbx 2014-02-28 14:44:12

As the type-safe-enum values aren't compile time constant (as normal enum values and strings are) you cannot use them wherever compile time constant values are required. In my use case that were Attributes but I imagine some more. The switch is however no problem, as you can implement such kind of stuff in the type-safe-enum class thus promoting it to be a smart enum.

@MikeH 2014-10-22 22:13:10

@JakubŠturc On the off chance you'll respond to this: How would I go about enumerating this like an enum Enum.GetValues()? The only thing I can think of is reflection in a static Enumerate() function.

@chrispepper1989 2014-12-10 10:31:01

would be interested in hearing @JakubŠturc thoughts on my answer, its really just a typedef of string which allows switch statements to work at the cost of dropping "val"

@Amadeus Sánchez 2015-12-01 15:02:30

@JakubŠturc link javacamp.org/designPattern/enum.html no longer works.

@SkyFighter 2016-04-13 17:03:55

Love the pattern, and have used it before in many forms, but perhaps the one thing that keeps taking me back to Enums is that I cannot use this TypeSafeEnum as a default value for a parameter since it is not a compile-time constant. Any ideas on a way around this hiccup?

@Rune Aamodt 2016-08-23 16:12:32

Works as long as the value doesn't need to be serialized.

@Jason Beck 2018-01-11 21:47:29

@SkyFighter if you look at deadlydog's version, which makes the int a public enum instead, you can use that for defaults or in a switch statement.

@Pangamma 2018-09-06 17:53:29

I originally used your implementation, but I thought it was annoying to have to keep writing so much code manually so I built some T4 templates to help out with it. stackoverflow.com/a/52209481/1582837 It provides ways to iterate over the values with Enum.Values. Might also assist with default values for parameters. @MikeH

@chrispepper1989 2014-12-10 10:30:15

A lot of great answers here but in my case did not solve what I wanted out of an "string enum", which was:

  1. Usable in a switch statement e.g switch(myEnum)
  2. Can be used in function parameters e.g. foo(myEnum type)
  3. Can be referenced e.g. myEnum.FirstElement
  4. I can use strings e.g. foo("FirstElement") == foo(myEnum.FirstElement)

1,2 & 4 can actually be solved with a C# Typedef of a string (since strings are switchable in c#)

3 can be solved by static const strings. So if you have the same needs, this is the simplest approach:

public sealed class Types
{

    private readonly String name;

    private Types(String name)
    {
        this.name = name;

    }

    public override String ToString()
    {
        return name;
    }

    public static implicit operator Types(string str)
    {
        return new Types(str);

    }
    public static implicit operator string(Types str)
    {
        return str.ToString();
    }


    #region enum

    public const string DataType = "Data";
    public const string ImageType = "Image";
    public const string Folder = "Folder";
    #endregion

}

This allows for example:

    public TypeArgs(Types SelectedType)
    {
        Types SelectedType = SelectedType
    }

and

public TypeObject CreateType(Types type)
    {
        switch (type)
        {

            case Types.ImageType:
              //
                break;

            case Types.DataType:
             //
                break;

        }
    }

Where CreateType can be called with a string or a type. However the downside is that any string is automatically a valid enum, this could be modified but then it would require some kind of init function...or possibly make they explicit cast internal?

Now if an int value was important to you (perhaps for comparison speed), you could use some ideas from Jakub Šturc fantastic answer and do something a bit crazy, this is my stab at it:

    public sealed class Types
{
    private static readonly Dictionary<string, Types> strInstance = new Dictionary<string, Types>();
    private static readonly Dictionary<int, Types> intInstance = new Dictionary<int, Types>();

    private readonly String name;
    private static int layerTypeCount = 0;
    private int value;
    private Types(String name)
    {
        this.name = name;
        value = layerTypeCount++;
        strInstance[name] = this;
        intInstance[value] = this;
    }

    public override String ToString()
    {
        return name;
    }


    public static implicit operator Types(int val)
    {
        Types result;
        if (intInstance.TryGetValue(val, out result))
            return result;
        else
            throw new InvalidCastException();
    }

    public static implicit operator Types(string str)
    {
        Types result;
        if (strInstance.TryGetValue(str, out result))
        {
            return result;
        }
        else
        {
            result = new Types(str);
            return result;
        }

    }
    public static implicit operator string(Types str)
    {
        return str.ToString();
    }

    public static bool operator ==(Types a, Types b)
    {
        return a.value == b.value;
    }
    public static bool operator !=(Types a, Types b)
    {
        return a.value != b.value;
    }

    #region enum

    public const string DataType = "Data";
    public const string ImageType = "Image";

    #endregion

}

but of course "Types bob = 4;" would be meaningless unless you had initialized them first which would sort of defeat the point...

But in theory TypeA == TypeB would be quicker...

@Michail Michailidis 2014-11-03 22:03:02

When I am in a situation like that I propose the solution below.

And as a consuming class you could have

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MyApp.Dictionaries
{
    class Greek
    {

        public static readonly string Alpha = "Alpha";
        public static readonly string Beta = "Beta";
        public static readonly string Gamma = "Gamma";
        public static readonly string Delta = "Delta";


        private static readonly BiDictionary<int, string> Dictionary = new BiDictionary<int, string>();


        static Greek() {
            Dictionary.Add(1, Alpha);
            Dictionary.Add(2, Beta);
            Dictionary.Add(3, Gamma);
            Dictionary.Add(4, Delta);
        }

        public static string getById(int id){
            return Dictionary.GetByFirst(id);
        }

        public static int getByValue(string value)
        {
            return Dictionary.GetBySecond(value);
        }

    }
}

And using a bidirectional dictionary: Based on this (https://stackoverflow.com/a/255638/986160) assuming that the keys will be associated with single values in the dictionary and similar to (https://stackoverflow.com/a/255630/986160) but a bit more elegant. This dictionary is also enumerable and you can go back and forth from ints to strings. Also you don't have to have any string in your codebase with the exception of this class.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;

namespace MyApp.Dictionaries
{

    class BiDictionary<TFirst, TSecond> : IEnumerable
    {
        IDictionary<TFirst, TSecond> firstToSecond = new Dictionary<TFirst, TSecond>();
        IDictionary<TSecond, TFirst> secondToFirst = new Dictionary<TSecond, TFirst>();

        public void Add(TFirst first, TSecond second)
        {
            firstToSecond.Add(first, second);
            secondToFirst.Add(second, first);
        }

        public TSecond this[TFirst first]
        {
            get { return GetByFirst(first); }
        }

        public TFirst this[TSecond second]
        {
            get { return GetBySecond(second); }
        }

        public TSecond GetByFirst(TFirst first)
        {
            return firstToSecond[first];
        }

        public TFirst GetBySecond(TSecond second)
        {
            return secondToFirst[second];
        }

        public IEnumerator GetEnumerator()
        {
            return GetFirstEnumerator();
        }

        public IEnumerator GetFirstEnumerator()
        {
            return firstToSecond.GetEnumerator();
        }

        public IEnumerator GetSecondEnumerator()
        {
            return secondToFirst.GetEnumerator();
        }
    }
}

@Mike 2014-01-24 15:57:25

I'm with Harvey but don't use const. I can mix and match string, int, whatever.

public class xlsLayout
{
    public int xlHeaderRow = 1;
    public int xlFirstDataRow = 2;
    public int xlSkipLinesBetweenFiles = 1; //so 0 would mean don't skip
    public string xlFileColumn = "A";
    public string xlFieldColumn = "B";
    public string xlFreindlyNameColumn = "C";
    public string xlHelpTextColumn = "D";
}

Then later ...

public partial class Form1 : Form
{
    xlsLayout xlLayout = new xlsLayout();

    xl.SetCell(xlLayout.xlFileColumn, xlLayout.xlHeaderRow, "File Name");
    xl.SetCell(xlLayout.xlFieldColumn, xlLayout.xlHeaderRow, "Code field name");
    xl.SetCell(xlLayout.xlFreindlyNameColumn, xlLayout.xlHeaderRow, "Freindly name");
    xl.SetCell(xlLayout.xlHelpTextColumn, xlLayout.xlHeaderRow, "Inline Help Text");
}

@Jeff Johnson 2014-06-17 13:59:35

I use Harvey's as well, but I do use the const access modifier because it is a compile time value and I can thus use them in switch statements. Using your code can work for certain situations, but you cannot use your values in a switch.

@Mangesh Pimpalkar 2012-02-11 00:15:17

I use an extension method:

public static class AttributesHelperExtension
    {
        public static string ToDescription(this Enum value)
        {
            var da = (DescriptionAttribute[])(value.GetType().GetField(value.ToString())).GetCustomAttributes(typeof(DescriptionAttribute), false);
            return da.Length > 0 ? da[0].Description : value.ToString();
        }
}

Now decorate the enum with:

public enum AuthenticationMethod
{
    [Description("FORMS")]
    FORMS = 1,
    [Description("WINDOWSAUTHENTICATION")]
    WINDOWSAUTHENTICATION = 2,
    [Description("SINGLESIGNON ")]
    SINGLESIGNON = 3
}

When you call

AuthenticationMethod.FORMS.ToDescription() you will get "FORMS".

@nawfal 2012-02-27 00:54:05

this is the shortest!

@elcool 2013-01-23 15:02:29

I had to add using System.ComponentModel; Also, this method only works if you want the String value to be the same as the Enum's name. OP wanted a different value.

@John Baughman 2013-03-14 21:46:31

@elcool: Just change the description text...

@nicodemus13 2014-02-01 19:56:43

Don't you mean when you call AuthenticationMethod.FORMS.ToDescription()?

@deadlydog 2014-01-20 21:13:47

I really like Jakub Šturc's answer, but it's shortcoming is that you cannot use it with a switch-case statement. Here's a slightly modified version of his answer that can be used with a switch statement:

public sealed class AuthenticationMethod
{
    #region This code never needs to change.
    private readonly string _name;
    public readonly Values Value;

    private AuthenticationMethod(Values value, String name){
        this._name = name;
        this.Value = value;
    }

    public override String ToString(){
        return _name;
    }
    #endregion

    public enum Values
    {
        Forms = 1,
        Windows = 2,
        SSN = 3
    }

    public static readonly AuthenticationMethod FORMS = new AuthenticationMethod (Values.Forms, "FORMS");
    public static readonly AuthenticationMethod WINDOWSAUTHENTICATION = new AuthenticationMethod (Values.Windows, "WINDOWS");
    public static readonly AuthenticationMethod SINGLESIGNON = new AuthenticationMethod (Values.SSN, "SSN");
}

So you get all of the benefits of Jakub Šturc's answer, plus we can use it with a switch statement like so:

var authenticationMethodVariable = AuthenticationMethod.FORMS;  // Set the "enum" value we want to use.
var methodName = authenticationMethodVariable.ToString();       // Get the user-friendly "name" of the "enum" value.

// Perform logic based on which "enum" value was chosen.
switch (authenticationMethodVariable.Value)
{
    case authenticationMethodVariable.Values.Forms: // Do something
        break;
    case authenticationMethodVariable.Values.Windows: // Do something
        break;
    case authenticationMethodVariable.Values.SSN: // Do something
        break;      
}

@kjhf 2014-02-05 21:42:24

A shorter solution would be to remove the enums {} and instead keep a static count of how many Enums you have constructed. This also gives the benefit that you don't have to add a new instance you make to the enum list. e.g. public static int nextAvailable { get; private set; } then in the constructor this.Value = nextAvailable++;

@deadlydog 2014-02-05 21:50:58

Interesting idea @kjhf. My concern though would be that if somebody reorders the code, then the value assigned to the enum values might change as well. For example, this could result in the wrong enum value being retrieved when the enum value is saved to a file/database, the order of the "new AuthenticationMethod(...)" lines are changed (e.g. one is removed), and then running the app again and retrieving the enum value from the file/database; the enum value may not match the AuthenticationMethod that was originally saved.

@kjhf 2014-02-05 22:30:57

Good point - though I hope in these particular cases people won't be relying on the enum's integer value (or reordering enum code.) -- and this value is purely used as a switch and possibly an alternative to .Equals() and .GetHashCode(). If concerned, you could always put a huge comment with "DO NOT REORDER" :p

@user1318499 2014-08-19 10:38:24

Can't you just overload the = operator to allow switch to work? I did this in VB and can now use it in select case statement.

@deadlydog 2014-08-19 22:22:51

@user1318499 No, C# has stricter rules around the switch statement than VB. You can't use class instances for the Case statement; you can only use constant primitives.

@chepe 2012-09-06 15:50:14

Just use the ToString() method

public enum any{Tomato=0,Melon,Watermelon}

To reference the string Tomato, just use

any.Tomato.ToString();

@Rafe 2012-09-23 06:52:14

Wow. That was easy. I know the OP wanted to add custom string descriptions, but this is what I needed. I should have known to try this, in retrospect, but I went down the Enum.GetName route.

@Brent 2014-04-22 19:13:19

Why is everyone else over-complicating this?

@Novitchi S 2014-04-23 13:35:16

@Brent Because most often you have the .ToString() value different than the user-friendly value you need.

@Hogan 2015-07-10 19:03:56

@Brent - because this is different than the question being asked. The question being ask is how to you get this string from a variable that has been assigned an enumerated value. That is dynamic at run time. This is checking the definition of the type and set at run time.

@Jack 2015-12-15 14:44:06

@chepe What about "Red Tomato" value???

@LiborV 2017-07-14 14:49:15

@Hogan - the ToString() works on variables as well: any fruit = any.Tomato; string tomato = fruit.ToString();

@Hogan 2017-07-14 20:16:02

@LiborV - please remember this was written in 09 -- C# was different then and ToString() on an instance of an enumeration did something different.

@Russ 2013-02-21 14:59:50

Here is yet another way to accomplish the task of associating strings with enums:

struct DATABASE {
    public enum enums {NOTCONNECTED, CONNECTED, ERROR}
    static List<string> strings =
        new List<string>() {"Not Connected", "Connected", "Error"};

    public string GetString(DATABASE.enums value) {
        return strings[(int)value];
    }
}

This method is called like this:

public FormMain() {
    DATABASE dbEnum;

    string enumName = dbEnum.GetString(DATABASE.enums.NOTCONNECTED);
}

You can group related enums in their own struct. Since this method uses the enum type, you can use Intellisense to display the list of enums when making the GetString() call.

You can optionally use the new operator on the DATABASE struct. Not using it means the strings List is not allocated until the first GetString() call is made.

@Bormagi 2013-02-15 19:21:19

Well, after reading all of the above I feel that the guys have over complicated the issue of transforming enumerators into strings. I liked the idea of having attributes over enumerated fields but i think that attributes are mainly used for Meta-data, but in your case i think that all you need is some sort of localization.

public enum Color 
{ Red = 1, Green = 2, Blue = 3}


public static EnumUtils 
{
   public static string GetEnumResourceString(object enumValue)
    {
        Type enumType = enumValue.GetType();
        string value = Enum.GetName(enumValue.GetType(), enumValue);
        string resourceKey = String.Format("{0}_{1}", enumType.Name, value);
        string result = Resources.Enums.ResourceManager.GetString(resourceKey);
        if (string.IsNullOrEmpty(result))
        {
            result = String.Format("{0}", value);
        }
        return result;
    }
}

Now if we try to call the above method we can call it this way

public void Foo()
{
  var col = Color.Red;
  Console.WriteLine (EnumUtils.GetEnumResourceString (col));
}

All you need to do is just create a resource file containing all the enumerator values and the corresponding strings

Resource Name          Resource Value
Color_Red              My String Color in Red
Color_Blue             Blueeey
Color_Green            Hulk Color

What is actually very nice about that is that it will be very helpful if you need your application to be localized, since all you need to do is just create another resource file with your new language! and Voe-la!

@harveyt 2013-02-06 13:46:33

for me, the pragmatic approach is class inside class, sample:

public class MSEModel
{
    class WITS
    {
        public const string DATE = "5005";
        public const string TIME = "5006";
        public const string MD = "5008";
        public const string ROP = "5075";
        public const string WOB = "5073";
        public const string RPM = "7001";
... 
    }

@Swati 2011-09-27 10:19:49

The approach i found for internationalization of Enums or getting text of Enums from respective Resource files is to create an attribute class by inheriting DescriptionAttribute class

public class EnumResourceAttribute : DescriptionAttribute
{

    public Type ResourceType { get; private set; }
    public string ResourceName { get; private set; }
    public int SortOrder { get; private set; }
    public EnumResourceAttribute(Type ResourceType,
                         string ResourceName,
                         int SortOrder)
    {

        this.ResourceType = ResourceType;
        this.ResourceName = ResourceName;
        this.SortOrder = SortOrder;
    }
}

Create another Static class that will provide extension methods for GetString and GetStrings.

public static class EnumHelper
{
    public static string GetString(this Enum value)
    {
        EnumResourceAttribute ea =
       (EnumResourceAttribute)value.GetType().GetField(value.ToString())
        .GetCustomAttributes(typeof(EnumResourceAttribute), false)
         .FirstOrDefault();
        if (ea != null)
        {
            PropertyInfo pi = ea.ResourceType
             .GetProperty(CommonConstants.ResourceManager);
            if (pi != null)
            {
                ResourceManager rm = (ResourceManager)pi
                .GetValue(null, null);
                return rm.GetString(ea.ResourceName);
            }

        }
        return string.Empty;
    }


    public static IList GetStrings(this Type enumType)
    {
        List<string> stringList = new List<string>();
        FieldInfo[] fiArray = enumType.GetFields();
        foreach (FieldInfo fi in fiArray)
        {
            EnumResourceAttribute ea =
                (EnumResourceAttribute)fi
                     .GetCustomAttributes(typeof(EnumResourceAttribute), false)
                     .FirstOrDefault();
            if (ea != null)
            {
                PropertyInfo pi = ea.ResourceType
                                    .GetProperty(CommonConstants.ResourceManager);
                if (pi != null)
                {
                    ResourceManager rm = (ResourceManager)pi
                                          .GetValue(null, null);
                    stringList.Add(rm.GetString(ea.ResourceName));
                }
            }
        }
        return stringList.ToList();
    }
}

And on the elements of your Enum you can write :

public enum Priority
{
     [EnumResourceAttribute(typeof(Resources.AdviceModule), Resources.ResourceNames.AdviceCreateAdviceExternaPriorityMemberHigh, 1)]
    High,
     [EnumResourceAttribute(typeof(Resources.AdviceModule), Resources.ResourceNames.AdviceCreateAdviceExternaPriorityMemberRoutine, 2)]
    Routine
}

Where Resources.ResourceNames.AdviceCreateAdviceExternaPriorityMemberHigh & Resources.ResourceNames.AdviceCreateAdviceExternaPriorityMemberRoutine are constants in the resource file or you can say the strings whose values can be available in different cultures.

If you are implementing your web application in MVC architecture then create a property

private IList result;
public IList Result
{
    get
    {
        result = typeof(Priority).GetStrings();
        return result;
    }
}

and in your .cshtml file you can just bind the enum to your dropdownlist like :

@Html.DropDownListFor(model => Model.vwClinicalInfo.Priority, new SelectList(Model.Result))

Thanks Ratnesh

@Charles Bretana 2009-01-08 14:19:49

Use method

Enum.GetName(Type MyEnumType,  object enumvariable)  

as in (Assume Shipper is a defined Enum)

Shipper x = Shipper.FederalExpress;
string s = Enum.GetName(typeof(Shipper), x);

There are a bunch of other static methods on the Enum class worth investigating too...

@lc. 2009-01-08 14:21:37

Exactly. I did make a custom attribute for a string description, but that's because I want a user-friendly version (with spaces and other special characters) that can be easily bound to a ComboBox or such.

@Keith 2009-01-08 14:26:08

Enum.GetName reflects the field names in the enum - same as the .ToString(). If performance is an issue it can be a problem. I wouldn't worry about it unless you're converting loads of enums though.

@Charles Bretana 2009-01-08 14:39:40

Another option to consider, if you need an enum with extra functiuonality, is to "roll yr own" using a struct... you add static readonly named properties to represent the enum values that are initialized to constructors that generate individual instances of the struct...

@Charles Bretana 2009-01-08 14:40:21

then you can add whatever other struct members you wish, to implement whatever functionality you want this "enum" to have ...

@Joel Coehoorn 2009-01-08 14:49:31

The issue here is that GetName is not localizable. That isn't always a concern, but it is something to be aware of.

@Ed S. 2011-02-03 22:18:33

@Charles: Yup, I've done that for enumerated values which require more advanced parsing logic.

@Charles Bretana 2011-02-04 00:26:39

@Ed, yes it's an extremely useful technique that not a lot of people are familar with

@Tyler Long 2012-08-05 14:33:30

why not Shipper.FederalExpress.ToString(). I tried in C# 4.0 and the result was the same as Enum.GetName

@Charles Bretana 2012-10-02 02:08:21

That only works if you explicitly have the specific member of the enum at compile time. If all you have is a variable that at run time might have any member of the enum assigned to it, you can't do that.

@Charles Bretana 2013-03-03 15:49:24

@tyler, and, since it only works at compile time, if you know which member you're after, in that case, why not, instead of Shipper.FederalExpress.ToString(), just put "FederalExpress" ?

@Tyler Long 2013-03-06 02:44:26

@CharlesBretana, I don't get your point. I don't have to know the memeber I am after. Suppose that it is a variable named x (just as the one in you answer), doesn't x.toString() work? I didn't try because it's long time since I wrote the last line of C#. if it doesn't work, then I get your point.

@Charles Bretana 2013-03-07 15:39:18

@tyler, I'll have to actually do it now to be sure, but as I recollect, unless you override it (which you can't do for an enum) ToString() on a variable just returns the type name. That's one reason why you override ToString() on other declared types as a matter of habit, to ensure that the debugger displays something useful (instead of just the typename) when looking at contents of collections and such.

@Mickey Perlstein 2012-05-07 15:01:01

My answer, working on @user29964 's answer (which is by far the simplest and closest to a Enum) is

 public class StringValue : System.Attribute
    {
        private string _value;

        public StringValue(string value)
        {
            _value = value;
        }

        public string Value
        {
            get { return _value; }
        }



        public static string GetStringValue(Enum Flagvalue)
        {
            Type type = Flagvalue.GetType();
            string[] flags = Flagvalue.ToString().Split(',').Select(x => x.Trim()).ToArray();
            List<string> values = new List<string>();

            for (int i = 0; i < flags.Length; i++)
            {

                FieldInfo fi = type.GetField(flags[i].ToString());

                StringValue[] attrs =
                   fi.GetCustomAttributes(typeof(StringValue),
                                           false) as StringValue[];
                if (attrs.Length > 0)
                {
                    values.Add(attrs[0].Value);
                }
            }
            return String.Join(",", values);

        }

usage

[Flags]
    public enum CompeteMetric
    {

        /// <summary>
        /// u
        /// </summary>
        [StringValue("u")]//Json mapping
        Basic_UniqueVisitors = 1 //Basic
             ,
        /// <summary>
        /// vi
        /// </summary>
        [StringValue("vi")]//json mapping
        Basic_Visits = 2// Basic
            ,
        /// <summary>
        /// rank
        /// </summary>
        [StringValue("rank")]//json mapping
        Basic_Rank = 4//Basic
 }

Example

        CompeteMetric metrics = CompeteMetric.Basic_Visits | CompeteMetric.Basic_Rank;
        string strmetrics = StringValue.GetStringValue(metrics);

this will return "vi,rank"

@Sec 2012-04-17 01:29:27

How I solved this as an extension method:

using System.ComponentModel;
public static string GetDescription(this Enum value)
{
    var descriptionAttribute = (DescriptionAttribute)value.GetType()
        .GetField(value.ToString())
        .GetCustomAttributes(false)
        .Where(a => a is DescriptionAttribute)
        .FirstOrDefault();

    return descriptionAttribute != null ? descriptionAttribute.Description : value.ToString();
}

Enum:

public enum OrderType
{
    None = 0,
    [Description("New Card")]
    NewCard = 1,
    [Description("Reload")]
    Refill = 2
}

Usage (where o.OrderType is a property with the same name as the enum):

o.OrderType.GetDescription()

Which gives me a string of "New Card" or "Reload" instead of the actual enum value NewCard and Refill.

@Bernie White 2012-04-21 10:03:32

For completeness you should include a copy of your DescriptionAttribute class.

@agentnega 2012-05-08 16:00:25

Bernie, DescriptionAttribute is in System.ComponentModel

@Razoomnick 2012-02-01 16:00:37

My variant

public struct Colors
{
    private String current;

    private static string red = "#ff0000";
    private static string green = "#00ff00";
    private static string blue = "#0000ff";

    private static IList<String> possibleColors; 

    public static Colors Red { get { return (Colors) red; } }
    public static Colors Green { get { return (Colors) green; } }
    public static Colors Blue { get { return (Colors) blue; } }

    static Colors()
    {
        possibleColors = new List<string>() {red, green, blue};
    }

    public static explicit operator String(Colors value)
    {
        return value.current;
    }

    public static explicit operator Colors(String value)
    {
        if (!possibleColors.Contains(value))
        {
            throw new InvalidCastException();
        }

        Colors color = new Colors();
        color.current = value;
        return color;
    }

    public static bool operator ==(Colors left, Colors right)
    {
        return left.current == right.current;
    }

    public static bool operator !=(Colors left, Colors right)
    {
        return left.current != right.current;
    }

    public bool Equals(Colors other)
    {
        return Equals(other.current, current);
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (obj.GetType() != typeof(Colors)) return false;
        return Equals((Colors)obj);
    }

    public override int GetHashCode()
    {
        return (current != null ? current.GetHashCode() : 0);
    }

    public override string ToString()
    {
        return current;
    }
}

Code looks a bit ugly, but usages of this struct are pretty presentative.

Colors color1 = Colors.Red;
Console.WriteLine(color1); // #ff0000

Colors color2 = (Colors) "#00ff00";
Console.WriteLine(color2); // #00ff00

// Colors color3 = "#0000ff"; // Compilation error
// String color4 = Colors.Red; // Compilation error

Colors color5 = (Colors)"#ff0000";
Console.WriteLine(color1 == color5); // True

Colors color6 = (Colors)"#00ff00";
Console.WriteLine(color1 == color6); // False

Also, I think, if a lot of such enums required, code generation (e.g. T4) might be used.

@junior software 2010-06-20 12:33:50

based on the MSDN: http://msdn.microsoft.com/en-us/library/cc138362.aspx

foreach (string str in Enum.GetNames(typeof(enumHeaderField)))
{
    Debug.WriteLine(str);
}

str will be the names of the fields

@Mickey Perlstein 2012-05-07 14:52:57

this will give the name of the enum, you can also use ToString() for that, this is not what was asked. checkout msdn.microsoft.com/en-us/library/system.enum.getname.aspx for more info about your bubu

@Ricardo Rivaldo 2011-08-18 19:29:54

Use object Enum.Parse(System.Type enumType, string value, bool ignoreCase); got it from http://blogs.msdn.com/b/tims/archive/2004/04/02/106310.aspx

@Bernie White 2012-04-21 10:04:46

You should revise this answer to include an example not just a link.

@Mickey Perlstein 2012-05-07 14:53:34

and read the question, same answer as above msdn.microsoft.com/en-us/library/system.enum.getname.aspx

@Paula Bean 2010-12-13 02:57:35

I wanted to post this as a comment to the post quoted below but couldn't because I don't have enough rep - so please don't down-vote. The code contained an error and I wanted to point this out to individuals trying to use this solution:

[TypeConverter(typeof(CustomEnumTypeConverter(typeof(MyEnum))]
public enum MyEnum
{
  // The custom type converter will use the description attribute
  [Description("A custom description")]
  ValueWithCustomDescription,
  // This will be exposed exactly.
  Exact
}

should be

[TypeConverter(typeof(CustomEnumTypeConverter<MyEnum>))]
public enum MyEnum
{
  // The custom type converter will use the description attribute
  [Description("A custom description")]
  ValueWithCustomDescription,

  // This will be exposed exactly.
  Exact
}

Brillant!

Related Questions

Sponsored Content

18 Answered Questions

[SOLVED] How to easily map c++ enums to strings

  • 2008-10-16 09:53:27
  • Roddy
  • 195228 View
  • 111 Score
  • 18 Answer
  • Tags:   c++ templates enums

26 Answered Questions

[SOLVED] Why not inherit from List<T>?

7 Answered Questions

[SOLVED] Enum with localized string in swift

17 Answered Questions

[SOLVED] Conveniently map between enum and int / String

4 Answered Questions

[SOLVED] Python3 - Convert enum to different datatypes

21 Answered Questions

[SOLVED] How do I have an enum bound combobox with custom string formatting for enum values?

  • 2009-04-28 07:21:23
  • Shalom Craimer
  • 82564 View
  • 132 Score
  • 21 Answer
  • Tags:   c# combobox enums

1 Answered Questions

[SOLVED] Can I use the enum int representation internally?

  • 2015-04-07 17:23:08
  • Martin Ueding
  • 74 View
  • 0 Score
  • 1 Answer
  • Tags:   c++ enums

2 Answered Questions

[SOLVED] casting a string to OdbcType enum

3 Answered Questions

[SOLVED] Arguments on properties

  • 2013-03-04 13:10:33
  • user1675891
  • 83 View
  • 0 Score
  • 3 Answer
  • Tags:   c# properties

6 Answered Questions

[SOLVED] string representation of an enum (estring)?

Sponsored Content