关于枚举更优雅的设计

时间:2011-07-26 10:33:24

标签: c# enums

我正在学习C#。

我听说C#是最具建设性的语言之一。那么你们会让我的代码更加优雅和高效吗?

public class ISO639
{
    public enum ISO639Code
    {
        Afrikaans,                      //af
        Albanian,                       //sq
        Amharic,                        //am

        ...

        Yiddish,                        //yi
        Unknown                         
    }


    public static string GetISO639CodeString(ISO639.ISO639Code l)
    {
        switch (l)
        {
            case ISO639Code.English: return "en";
            case ISO639Code.Japanese: return "ja";

            ...

            case ISO639Code.Hebrew: return "he";
            default: return "";
        }


    public static ISO639.ISO639Code GetISO39CodeValue(string s)
    {

        switch (s)
        {
            case "ko" : return ISO639Code.Korean;
            case "en" : return ISO639Code.English;

            ...

            case "hu" : return ISO639Code.Hungarian;
            default: return ISO639Code.Unknown;
        }
    }
}

这是我的班级ISO639。此类为ISO639代码提供枚举,但我需要从ISO639枚举到纯字符串的类型转换。 (例如ISO639.ISO639Code.Italian =>“it”)。我还需要从普通字符串到ISO639枚举的类型转换。 (例如“it”=> ISO639.ISO639Code.Italian)。

是否有更有效的编码风格?

9 个答案:

答案 0 :(得分:9)

您可以为每个枚举条目添加标准 System.ComponentModel.Description属性,然后阅读它。

public enum ISO639Code       
{ 
  [Description("af")]
  Afrikaans
}

public static class EnumExtensions
{
    // Extension method to read Description value
    public static string GetDescription(this Enum currentEnum)
    {
         var fi = currentEnum.GetType().GetField(currentEnum.ToString()); 
         var da = (DescriptionAttribute)Attribute.GetCustomAttribute(fi, typeof(DescriptionAttribute)); 
         return da != null ? da.Description : currentEnum.ToString();
     } 
}

// **How-to read it**
ISO639Code isoCode = ISO639Code.Afrikaans;

// this will returns "af"
string isoDescription = isoCode.GetDescription(); 

修改

    string searchFor = "af"; 
    ISO639Code foundEntry;

    // Loop through all entries descriptions       
    var allEntries = Enum.GetValues(typeof(ISO639Code));
    foreach (var entry in allEntries)
    {
        // If you will extract this as separate method and use it for search not only loop
        // through the all entries - you can put here is yield return description
        var currentEntry = ((ISO639Code)entry);
        string description = currentEntry.GetDescription();
        if (description == searchFor)
        {
            foundEntry = currentEntry;
            break;
        }
    }

答案 1 :(得分:8)

不确定。您可以使用attributes

public enum ISO639Code
{
    [CodeString("af")] Afrikaans,
    [CodeString("sq")] Albanian,    
}

答案 2 :(得分:2)

我建议你使用C#扩展方法来枚举,它们允许你添加你想要的任何逻辑。

例如,请参阅http://pietschsoft.com/post/2008/07/c-enhance-enums-using-extension-methods.aspx

答案 3 :(得分:2)

使用字典,例如:new Dictionary<ISO639Code, string>

答案 4 :(得分:1)

我只是将信息存储在类似字典的对象中。这样,您可以按键引用名称并直接获取值。

答案 5 :(得分:0)

你有一个枚举:

 public enum ISO639Code
 {
    Afrikaans = 1,                      
    Albanian  = 2,                       
    Amharic   = 3, 

创建数据库表:

 ISO639Id   int   PK,
 ISO639Code char(2)

ISO639Id映射到枚举值。

在代码中,您需要一个ISO630类,其中包含从数据库中读取的Id和Code值。 (您可以加载一次,然后将其缓存在内存中。)

这种方法的优点在于它可以轻松扩展,以便将来您想为每个ISO639代码存储更多信息,您只需添加另一个字段。

答案 6 :(得分:0)

查看System.Globailzation命名空间。您需要的功能似乎已在那里实现。在最坏的情况下,您可以看到.Net框架中应用的体系结构和技术可以解决非常类似的问题。

答案 7 :(得分:0)

枚举非常适合在代码中工作,因为它们实际上是强类型的,并且使重构更容易。 请按照以下步骤操作:

  1. 将属性用于要附加到枚举的任何额外信息。通常这是一个简单的Description属性。类似的东西:

    public enum IsoCodes {     [描述( “AF”)]     非洲人= 0,     [描述( “AM”)]     美国人= 1 }

  2. 然后编写一些扩展方法,将字符串和整数转换为此枚举:

    public static string GetDescription(this Enum value)
            {
                var entries = value.ToString().Split(FlagEnumSeparatorCharacter);
    
                var description = new string[entries.Length];
    
                for (var i = 0; i < entries.Length; i++)
                {
                    var fieldInfo = value.GetType().GetField(entries[i].Trim());
                    var attributes = fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false) as DescriptionAttribute[];
                    description[i] = (attributes.Length > 0) ? attributes[0].Description : entries[i].Trim();
                }
    
                return String.Join(", ", description);
            }
    
    public static int GetValue(this Enum value)
        {
            return (int)value.GetType().GetField(value.ToString()).GetRawConstantValue();
        }
    
        public static T ToEnum<T>(this string value)
        {
            if (typeof(T).BaseType.Name != typeof(Enum).Name)
            {
                throw new Exception("Not an enum");
            }
            return (T)Enum.Parse(typeof(T), value, true);
        }
    
        public static T ToEnum<T>(this int value)
        {
            if (typeof(T).BaseType.Name != typeof(Enum).Name)
            {
                throw new Exception("Not an enum");
            }
            return (T)Enum.ToObject(typeof(T), value);
        }
    

    现在可以随意使用你的枚举。

答案 8 :(得分:0)

我会选择ISO639Code作为课程而非enum:

public class ISO639Code
{
    public string Value { get; set ; }
    public string Code { get; set; }

    public ISO639Code()
    {
        this.Value = "";
        this.Code = "";
    }

    public ISO639Code(string value, string code)
        : this()
    {
        this.Value = value;
        this.Code = code;
    }

    public override bool Equals(object obj)
    {
        if (obj != null)
        {
            if (obj is string)
                return obj.ToString().Equals(this.Value, StringComparison.CurrentCultureIgnoreCase);
            if (obj is ISO639Code)
                return ((ISO639Code)obj).Value.Equals(this.Value, StringComparison.CurrentCultureIgnoreCase);
        }
        return false;
    }

    public override int GetHashCode()
    {
        return this.Value.GetHashCode();
    }

    public override string ToString()
    {
        return this.Value;
    }
}

然后让全局List<ISO639Code>包含所有可能的代码,并根据代码名称或值查找特定代码,只需在列表中搜索。

就个人而言,我更倾向于调整枚举。