枚举字符串值并按值查找枚举

时间:2010-08-17 11:38:05

标签: c# enums

我希望有一个类似下面的枚举,然后有一个类似于Util.FindFruitByValue(“A”)的方法返回枚举Apple。这是因为缩写存储在数据库中,我需要在从db读取后将它们转换为适当的枚举。这是可能的还是我需要为它创建一个单独的类?请告诉我。提前谢谢。

public enum Fruit
{
    Apple = "A"
    Banana = "B"
    Cherry = "C"
}

更新:这就像一个查找表,但区别在于值是字符串而不是int。我通过从数据库中读取值来填充业务对象,我想使用具有固定值的类型而不是字符串。

7 个答案:

答案 0 :(得分:20)

我通过在枚举上使用Description属性解决了这个问题。解决方案如下。我使用扩展方法来获取描述。获取描述的代码来自此链接http://blog.spontaneouspublicity.com/post/2008/01/17/Associating-Strings-with-enums-in-C.aspx。谢谢你的回复。

    public enum Fruit
{
    [Description("Apple")]
    A,
    [Description("Banana")]
    B,
    [Description("Cherry")]
    C
}

public static class Util
{
    public static T StringToEnum<T>(string name)
    {
        return (T)Enum.Parse(typeof(T), name);
    }

    public static string ToDescriptionString(this Enum value)
    {
        FieldInfo fi = value.GetType().GetField(value.ToString());

        DescriptionAttribute[] attributes =
            (DescriptionAttribute[])fi.GetCustomAttributes(
            typeof(DescriptionAttribute),
            false);

        if (attributes != null &&
            attributes.Length > 0)
            return attributes[0].Description;
        else
            return value.ToString();
    }
}

答案 1 :(得分:12)

您可以将值放在Dictionary中以有效地查找它们:

Dictionary<string, Fruit> fruitValues = new Dictionary<string, Fruit>();
fruitValues.Add("A", Fruit.Apple);
fruitValues.Add("B", Fruit.Banana);
fruitValues.Add("C", Fruit.Cherry);

查找

string dataName = "A";
Fruit f = fruitValues[dataName];

如果该值可能不存在:

string dataName = "A";
Fruit f;
if (fruitValues.TryGetValue(dataName, out f)) {
  // got the value
} else {
  // there is no value for that string
}

答案 2 :(得分:2)

我写了一个库来处理这个问题。它本来只是为了反过来(从和Enum返回一个字符串值),但是一旦我写了,能够将一个字符串解析回它的Enum,只是一小步。

该库名为EnumStringValues,可从VS中的nuget获得(包页也在这里:https://www.nuget.org/packages/EnumStringValues) SourceCode在GitHub上:https://github.com/Brondahl/EnumStringValues

欢迎提出想法和意见。 灵感显然来自于其他答案中引用的广为人知的属性方法。

答案 3 :(得分:1)

如何使用Hashtable?

答案 4 :(得分:1)

对不起,我忽略了OP的Enum的定义。 显然,Enum值必须是数字类型,因此OP的定义不起作用。

我想到的是将char值用作Enum值,例如:

public enum Fruit
{
    Apple  = 65, //"A",
    Banana = 66, // "B",
    Cherry = 67 //"C"
}

根据Convert.ToInt32('A') - 不知道如何处理区分大小写。 然后,通过强制转换获取正确的结果。我还在玩一个例子,很高兴听到一些建议。

好的,抱歉延误了。以下是对此的更多信息:

public static class EnumConverter<T>
{
    public static T ToEnum(char charToConvert, out bool success)
    {
        try
        {                
            int intValue = Convert.ToInt32(charToConvert);                
            if (Enum.IsDefined(typeof(T), intValue))
            {
                success = true;
                return (T)Enum.ToObject(typeof(T), intValue);
            }
       }
       catch (ArgumentException ex)
       {
               // Use your own Exception Management Here
       }
       catch (InvalidCastException ex)
       {
           // Use your own Exception Management Here
       }
       success = false;
       return default(T);
    }
}

用法:

bool success = false;
Fruit selected = EnumConverter<Fruit>.ToEnum('A', out success);
if (success)
{
   // go for broke
}

答案 5 :(得分:0)

我制作了一个小的DynamicEnum类,可以很容易地将枚举进出域和数据存储库。

public abstract class DynamicEnum<T> : IEquatable<T>, IComparable<T>
    where T : DynamicEnum<T>, new()
{
    #region Instance

    public int PathCode { get; private set; }
    public string PathValue { get; private set; }

    protected DynamicEnum() { }

    protected DynamicEnum(int pathCode, string pathValue)
    {
        PathCode = pathCode;
        PathValue = PathValue;
    }

    #region IEquatable<AreaStatus> Members

    public bool Equals(T other)
    {
        return PathCode == other.PathCode;
    }

    #endregion

    public override bool Equals(object obj)
    {
        return Equals(obj as T);
    }

    public override int GetHashCode()
    {
        return PathCode.GetHashCode();
    }

    #region IComparable<AreaStatus> Members

    public int CompareTo(T other)
    {
        return PathCode.CompareTo(other.PathCode);
    }

    #endregion

    #endregion

    #region Class / Static

    static DynamicEnum()
    {
        // Despite appearances, static methods are not really inherited by
        // child classes. This means when the mapping fields below are accessed
        // by an implementing class the CLR does not see it as a method on that
        // class. In the event that the implementing class's static constructor
        // hasn't been called yet, it will not be called at that point since
        // technically no static method/property or instance of the implementing
        // class has been used. Working around this by creating an instance here
        // which causes the derived class's static constructor to be called
        // beforehand. This could alternately be solved by moving the default 'enum'
        // value initialization out of the implementing classes to the Global.asax 
        // where the database 'enum' values are optionally loaded.
        new T();
    }

    public static void Initialize(IEnumerable<T> statuses)
    {
        IntoDomainMapping = statuses.ToDictionary(x => x.PathValue, x => x);
        IntoDBMapping = IntoDomainMapping.ToDictionary(x => x.Value, x => x.Key);
    }

    public static Dictionary<string, T> IntoDomainMapping { get; protected set; }
    public static Dictionary<T, string> IntoDBMapping { get; protected set; }

    #endregion

    #region Operator Overloads

    public static bool operator ==(DynamicEnum<T> s1, T s2)
    {
        return s1.Equals(s2);
    }

    public static bool operator !=(DynamicEnum<T> s1, T s2)
    {
        return !s1.Equals(s2);
    }

    public static bool operator >(DynamicEnum<T> s1, T s2)
    {
        return s1.CompareTo(s2) > 0;
    }

    public static bool operator <(DynamicEnum<T> s1, T s2)
    {
        return s1.CompareTo(s2) < 0;
    }

    public static bool operator >=(DynamicEnum<T> s1, T s2)
    {
        return s1.CompareTo(s2) >= 0;
    }

    public static bool operator <=(DynamicEnum<T> s1, T s2)
    {
        return s1.CompareTo(s2) <= 0;
    }

    #endregion
}

这是“Enum”类

    public class ResourcePath : DynamicEnum<ResourcePath>
{
    public ResourcePath() { }

    public ResourcePath(int pathCode, string pathValue) 
        : base(pathCode, pathValue) { }


    static ResourcePath()
    {
        Initialize(new List<ResourcePath>
            {
                new ResourcePath(1, "customer.list"),
                new ResourcePath(1, "customer.create"),
                new ResourcePath(1, "customer.info"),
                new ResourcePath(1, "customer.update"),
                new ResourcePath(1, "customer.delete"),
            });
    }

    public static ResourcePath Deleted
    { 
        get { return ResourcePath.IntoDomainMapping["DE"]};
    }
}

最后基本用法

var resource = GetAllResources().Where(e => e.PathCode == pathCode).firstOrDefault();

答案 6 :(得分:0)

我知道这是一个老帖子,但我遇到了类似的问题,我昨天找到了解决方案。

您可以使用类型安全枚举模式,如下文所述:

https://stackoverflow.com/a/424414/1257584