我有以下列举:

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

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

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


当前回答

使用对象枚举. parse(系统。类型枚举类型,字符串值,bool ignoreCase);从http://blogs.msdn.com/b/tims/archive/2004/04/02/106310.aspx获取

其他回答

用. net 4.0及以上版本解决这个问题非常简单。不需要其他代码。

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

获取字符串about只需使用:

MyStatus.Active.ToString("f");

or

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

取值为Active或Archived。

当调用Enum时,查看不同的字符串格式(上面的“f”)。ToString参见此枚举格式字符串页面

如果我理解正确,你可以简单地使用.ToString()从值中检索enum的名称(假设它已经被转换为enum); 如果你有裸整型(比如从数据库或其他地方),你可以先将它强制转换为枚举。 下面的两个方法都将获得枚举名称。

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

但是请记住,第二种技术假设您使用的是int型,并且您的索引基于1(而不是基于0)。相比之下,GetNames函数也相当繁重,每次调用它都要生成一个完整的数组。 正如您在第一种技术中看到的,. tostring()实际上是隐式调用的。 这两个问题都已经在答案中提到了,当然,我只是想澄清它们之间的区别。

我真的很喜欢Jakub Šturc的答案,但它的缺点是不能与开关case语句一起使用。下面是他的回答的一个稍微修改的版本,可以与switch语句一起使用:

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

所以你得到了Jakub Šturc的答案的所有好处,另外我们可以像这样使用switch语句:

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

使用对象枚举. parse(系统。类型枚举类型,字符串值,bool ignoreCase);从http://blogs.msdn.com/b/tims/archive/2004/04/02/106310.aspx获取

我使用系统中的Description属性。ComponentModel名称空间。简单地装饰枚举,然后使用下面的代码来检索它:

public static string GetDescription<T>(this object enumerationValue)
            where T : struct
        {
            Type type = enumerationValue.GetType();
            if (!type.IsEnum)
            {
                throw new ArgumentException("EnumerationValue must be of Enum type", "enumerationValue");
            }

            //Tries to find a DescriptionAttribute for a potential friendly name
            //for the enum
            MemberInfo[] memberInfo = type.GetMember(enumerationValue.ToString());
            if (memberInfo != null && memberInfo.Length > 0)
            {
                object[] attrs = memberInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);

                if (attrs != null && attrs.Length > 0)
                {
                    //Pull out the description value
                    return ((DescriptionAttribute)attrs[0]).Description;
                }
            }
            //If we have no description attribute, just return the ToString of the enum
            return enumerationValue.ToString();

        }

举个例子:

public enum Cycle : int
{        
   [Description("Daily Cycle")]
   Daily = 1,
   Weekly,
   Monthly
}

这段代码很好地满足了不需要“友好名称”的枚举,只返回枚举的. tostring()。