我有以下列举:

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

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

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


当前回答

在你的问题中,你从未说过你实际上需要枚举的数值。

如果你不这样做,只是需要一个string类型的枚举(这不是一个整型,所以不能是enum的基)这里有一个方法:

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

您可以使用与enum相同的语法来引用它

if (bla == AuthenticationMethod.FORMS)

它将比使用数值(比较字符串而不是数字)稍微慢一些,但从好的方面来看,它不使用反射(慢)来访问字符串。

其他回答

使用方法

Enum.GetName(Type MyEnumType,  object enumvariable)  

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

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

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

我如何解决这个扩展方法:

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

枚举:

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

用法(其中o.OrderType是一个与enum同名的属性):

o.OrderType.GetDescription()

这给了我一个字符串的“新卡”或“重载”,而不是实际的enum值NewCard和重新填充。

只需使用ToString()方法

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

要引用字符串Tomato,只需使用

any.Tomato.ToString();

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

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

. 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"

当我遇到这样的问题时,我首先会试图找到以下几个问题的答案:

枚举值的名称是否足够友好,或者我需要提供更友好的名称? 我需要往返吗?也就是说,我是否需要将文本值解析为枚举值? 这是我需要为我的项目中的许多枚举做的事情,还是只有一个? 我将在什么样的UI元素中呈现这些信息-特别是,我将绑定到UI,还是使用属性表? 这需要本地化吗?

最简单的方法是使用Enum。GetValue(并使用枚举. parse支持往返)。正如Steve Mitcham所建议的那样,构建一个TypeConverter来支持UI绑定通常也是值得的。(在使用属性表时,没有必要构建TypeConverter,这是属性表的优点之一。尽管天晓得他们也有自己的问题。)

一般来说,如果上述问题的答案表明这是行不通的,我的下一步是创建和填充一个静态Dictionary<MyEnum,字符串>,或者可能是一个Dictionary<Type, Dictionary<int,字符串>>。我倾向于跳过中间的用属性装饰代码的步骤,因为接下来通常需要在部署后更改友好值(通常,但不总是,因为本地化)。