C#获取枚举值

nei*_*man 30 .net c# string enums

我有一个包含以下内容的枚举(例如):

  • 英国,
  • UnitedStates的,
  • 法国,
  • 葡萄牙

在我的代码中,我使用Country.UnitedKingdom,但是如果我将它分配给字符串,我希望将值设置为UK.

这可能吗?

Jon*_*eet 53

您不能将枚举值分配给要开始的字符串.你必须打电话ToString(),这将转换Country.UnitedKingdom为"UnitedKingdom".

两个选项表明自己:

  • 创建一个 Dictionary<Country, string>
  • 一个开关声明
  • 使用属性装饰每个值,并使用反射加载它

关于他们每个人的评论......

示例代码 Dictionary<Country,string>

using System;
using System.Collections.Generic;

enum Country
{
    UnitedKingdom, 
    UnitedStates,
    France,
    Portugal
}

class Test
{
    static readonly Dictionary<Country, string> CountryNames =
        new Dictionary<Country, string>
    {
        { Country.UnitedKingdom, "UK" },
        { Country.UnitedStates, "US" },
    };

    static string ConvertCountry(Country country) 
    {
        string name;
        return (CountryNames.TryGetValue(country, out name))
            ? name : country.ToString();
    }

    static void Main()
    {
        Console.WriteLine(ConvertCountry(Country.UnitedKingdom));
        Console.WriteLine(ConvertCountry(Country.UnitedStates));
        Console.WriteLine(ConvertCountry(Country.France));
    }
}
Run Code Online (Sandbox Code Playgroud)

您可能希望将逻辑ConvertCountry放入扩展方法中.例如:

// Put this in a non-nested static class
public static string ToBriefName(this Country country) 
{
    string name;
    return (CountryNames.TryGetValue(country, out name))
        ? name : country.ToString();
}
Run Code Online (Sandbox Code Playgroud)

然后你可以写:

string x = Country.UnitedKingdom.ToBriefName();
Run Code Online (Sandbox Code Playgroud)

正如评论中所提到的,默认字典比较器将涉及拳击,这是非理想的.对于一次性,我会忍受它,直到我发现它是一个瓶颈.如果我为多个枚举做这个,我会写一个可重用的类.

切换声明

我同意yshuditelu的回答,建议switch对相对较少的案例使用陈述.但是,由于每个案例都是一个单一的陈述,我个人会改变我的编码风格,以保持代码紧凑但可读:

public static string ToBriefName(this Country country) 
{
    switch (country)
    {
        case Country.UnitedKingdom:  return "UK";
        case Country.UnitedStates:   return "US";
        default:                     return country.ToString();
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以添加更多案例而不会变得太大,并且很容易将您的眼睛从枚举值转换为返回值.

DescriptionAttribute

Rado关于DescriptionAttribute可重用代码的观点很好,但在这种情况下,我建议每次需要获取值时都不要使用反射.我可能会编写一个通用的静态类来保存一个查找表(可能是一个Dictionary,可能还有注释中提到的自定义比较器).扩展方法不能在泛型类中定义,所以你可能会得到类似的东西:

public static class EnumExtensions
{
    public static string ToDescription<T>(this T value) where T : struct
    {
        return DescriptionLookup<T>.GetDescription(value);
    }

    private static class DescriptionLookup<T> where T : struct
    {
        static readonly Dictionary<T, string> Descriptions;

        static DescriptionLookup()
        {
            // Initialize Descriptions here, and probably check
            // that T is an enum
        }

        internal static string GetDescription(T value)
        {
            string description;
            return Descriptions.TryGetValue(value, out description)
                ? description : value.ToString();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 当我看到一些实际证据表明它造成了瓶颈时,我只会担心这一点.与以往一样,使用最简单的代码,直到您有充分的理由去做其他事情.在我看来,"表现可怕"和"表现不佳"之间存在很大差异. (10认同)

Sco*_*vey 23

我更喜欢在我的枚举上使用DescriptionAttribute.然后,您可以使用以下代码从枚举中获取该描述.

enum MyCountryEnum
{    
    [Description("UK")]
    UnitedKingdom = 0,    

    [Description("US")]
    UnitedStates = 1,    

    [Description("FR")]
    France = 2,    

    [Description("PO")]
    Portugal = 3
}

public static string GetDescription(this Enum value)
{
    var type = value.GetType();

    var fi = type.GetField(value.ToString());

    var descriptions = fi.GetCustomAttributes(typeof(DescriptionAttribute), false) as DescriptionAttribute[];

    return descriptions.Length > 0 ? descriptions[0].Description : value.ToString();
}

public static SortedDictionary<string, T> GetBoundEnum<T>() where T : struct, IConvertible
{
    // validate.
    if (!typeof(T).IsEnum)
    {
        throw new ArgumentException("T must be an Enum type.");
    }

    var results = new SortedDictionary<string, T>();

    FieldInfo[] fieldInfos = typeof(T).GetFields();

    foreach (var fi in fieldInfos)
    {

        var value = (T)fi.GetValue(fi);
        var description = GetDescription((Enum)fi.GetValue(fi));

        if (!results.ContainsKey(description))
        {
            results.Add(description, value);
        }
    }
    return results;
}
Run Code Online (Sandbox Code Playgroud)

然后得到我的绑定枚举列表,它只是一个调用

GetBoundEnum<MyCountryEnum>()
Run Code Online (Sandbox Code Playgroud)

要获得单个枚举的描述,您只需使用这样的扩展方法

string whatever = MyCountryEnum.UnitedKingdom.GetDescription();
Run Code Online (Sandbox Code Playgroud)


Tim*_*ter 15

您可以创建一个扩展方法public static string ToShortString(this Country country).在该方法中,您可以使用Jon建议的静态字典,或者您可以简单地执行切换案例.

例:

public static class CountryExtensions
{
    public static string ToShortString( this Country target )
    {
        switch (target) {
            case Country.UnitedKingdom:
                return "UK";
            case Country.UnitedStates:
                return "US";
            case Country.France:
                return "FR";
            case Country.Portugal:
                return "PT";
            default:
                return "None";
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


rei*_*ein 6

伪代码:

enum MyCountryEnum
{
    UnitedKingdom = 0,
    UnitedStates = 1,
    France = 2,
    Portugal = 3,
}

string[] shortCodes = new string[] {"UK", "US", "FR", "PO"};


MyCountryEnum enumValue = MyCountryEnum.UnitedKingdom;
string code = shortCodes[enumValue];
Run Code Online (Sandbox Code Playgroud)

  • 这种维护开销令人担忧.保持两个未连接的数据结构同步始终是一个红旗. (7认同)