我有以下列举:

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

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

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


当前回答

选项1:

public sealed class FormsAuth
{
     public override string ToString{return "Forms Authtentication";}
}
public sealed class WindowsAuth
{
     public override string ToString{return "Windows Authtentication";}
}

public sealed class SsoAuth
{
     public override string ToString{return "SSO";}
}

然后

object auth = new SsoAuth(); //or whatever

//...
//...
// blablabla

DoSomethingWithTheAuth(auth.ToString());

选项2:

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

public class MyClass
{
    private Dictionary<AuthenticationMethod, String> map = new Dictionary<AuthenticationMethod, String>();
    public MyClass()
    {
         map.Add(AuthenticationMethod.FORMS,"Forms Authentication");
         map.Add(AuthenticationMethod.WINDOWSAUTHENTICATION ,"Windows Authentication");
         map.Add(AuthenticationMethod.SINGLESIGNON ,"SSo Authentication");
    }
}

其他回答

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

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

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

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

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

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

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

我很清楚这个问题已经被回答了,而且OP已经对接受的答案感到满意。但我发现大多数答案,包括公认的答案,都有点复杂。

我有一个项目给了我这样的情况,我能够以这种方式实现它。

首先,你必须考虑枚举名称的大小写:

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

然后,有这个扩展:

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

通过这种方法,您可以将每个枚举名称转换为字符串表示形式,每个单词用空格分隔。例:

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

对我来说,实用的方法是类中类,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";
... 
    }

老帖子,但是…

这个问题的答案其实很简单。使用enumel . tostring()函数

这个函数有6个重载,你可以使用enumenumtostring ("F")或enumenumtostring()来返回字符串值。没必要为其他事操心。这是一个正在运行的演示

注意,这个解决方案可能不适用于所有编译器(这个演示没有像预期的那样工作),但至少它适用于最新的编译器。