我有以下列举:

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

然而问题是,当我请求AuthenticationMethod时,我需要“FORMS”这个词。表单而不是id

对于这个问题,我找到了以下解决方案(链接):

首先,我需要创建一个自定义属性“StringValue”:

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

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

    public string Value
    {
        get { return _value; }
    }

}

然后我可以将这个属性添加到我的枚举器中:

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

当然,我需要一些东西来检索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;
    }
}

很好,现在我已经有了工具来获取枚举器的字符串值。 然后我可以这样使用它:

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

好的,现在所有这些工作就像一个魅力,但我发现它有很多工作。我想知道有没有更好的解决办法。

我还尝试了一些字典和静态属性,但这也不是更好。


当前回答

当我遇到这样的情况时,我提出下面的解决方案。

作为一个消费阶级,你可以有

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);
        }

    }
}

使用双向字典: 基于此(https://stackoverflow.com/a/255638/986160),假设键将与字典中的单个值相关联,类似于(https://stackoverflow.com/a/255630/986160),但更优雅一些。这个字典也是可枚举的,你可以在整型和字符串之间来回切换。此外,除了这个类,你的代码库中不需要有任何字符串。

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();
        }
    }
}

其他回答

如果你来这里是为了实现一个简单的“Enum”,但其值是字符串而不是int,这里有一个最简单的解决方案:

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

实现:

var someStringVariable = MetricValueList.Brand;

我发现的Enums国际化或从各自的资源文件获取Enums文本的方法是通过继承DescriptionAttribute类创建一个属性类

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;
    }
}

创建另一个Static类,为GetString和GetString提供扩展方法。

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();
    }
}

在Enum的元素上,你可以这样写:

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 . resourcename . advicecreateadviceexternaprioritymemberroutine是资源文件中的常量,或者你可以说字符串,其值可以在不同的文化中可用。

如果你在MVC架构中实现你的web应用程序,那么创建一个属性

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

在你的.cshtml文件中,你可以像这样将枚举绑定到你的下拉列表:

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

谢谢 Ratnesh

使用方法

Enum.GetName(Type MyEnumType,  object enumvariable)  

如(假设Shipper是一个已定义的Enum)

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

Enum类上还有很多其他的静态方法也值得研究……

基于MSDN: http://msdn.microsoft.com/en-us/library/cc138362.aspx

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

STR将是字段的名称

不幸的是,在枚举上获取属性的反射非常慢:

看这个问题:有人知道一种快速获取枚举值的自定义属性的方法吗?

. tostring()在枚举上也相当慢。

你可以为枚举写扩展方法:

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

这不是很好,但是很快,而且不需要对属性或字段名进行反射。


c# 6更新

如果你可以使用c# 6,那么操作符的新名称适用于枚举,因此nameof(myenume .WINDOWSAUTHENTICATION)将在编译时转换为“WINDOWSAUTHENTICATION”,使其成为获取枚举名称的最快方式。

注意,这将显式枚举转换为内联常量,因此它不适用于变量中的枚举。所以:

nameof(AuthenticationMethod.FORMS) == "FORMS"

但是…

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