Wednesday, May 1, 2013

使用列舉的描述功能 Using Enum with Description

眾所皆知,在程式中遇到魔術數字是很擾人的,不但降低可讀性,除錯時也增加困擾,所以通常是建議使用一些增加可讀性的方式去取代,例如使用列舉型別(Enumeration)去將這些魔術數字轉變成比較好讀的形式,但是列舉預設只能塞int,雖然可以直接把列舉名稱toString拿來用,但是如果要有特殊符號(如空白)就沒辦法了。
public enum Country
{
    Afghanistan,
    Albania,
    Algeria,
    Andorra,
    Angola,
    AntiguaAndBarbuda,//Antigua and Barbuda
    Argentina
}

在這時候,我們可以利用Description的屬性去把我們想要的資訊塞進去。



先貼 code 再解釋
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Reflection;

namespace Test
{
    class Program
    {
        static void Main()
        {
            foreach (var u in EnumToList<Urban>())
            {
                Console.WriteLine(u + " = " + (int)u + " ,description = " + GetEnumDescription(u));
            }
            Console.WriteLine();
            Console.WriteLine(Urban.L33T + ">" + Urban.Uber + " ? " + (Urban.L33T > Urban.Uber));
            Console.WriteLine(Urban.Yolo+"'s description = "+ GetEnumDescription((Urban.Yolo)));
            Console.WriteLine(Urban.Vsre+"'s value = "+(int)Urban.Vsre);
            Console.ReadLine();
        }

        public static string GetEnumDescription(Enum value)
        {
            FieldInfo fi = value.GetType().GetField(value.ToString());
            var attributes = (DescriptionAttribute[]) fi.GetCustomAttributes(typeof (DescriptionAttribute), false);
            return attributes.Length > 0 ? attributes[0].Description : value.ToString();
        }

        public static IEnumerable<T> EnumToList<T>()
        {
            Type enumType = typeof(T);
           if (enumType.BaseType != typeof(Enum))
                throw new ArgumentException("T must be of type System.Enum");
            Array enumValArray = Enum.GetValues(enumType);
            var enumValList = new List<T>(enumValArray.Length);
            enumValList.AddRange(from int val in enumValArray select (T) Enum.Parse(enumType, val.ToString(CultureInfo.InvariantCulture)));
            return enumValList;
        }
    }

    public enum Urban
    {
        /// <summary>
        /// l33t
        /// </summary>
        [Description("elite")]
        L33T = -1,
        /// <summary>
        /// Über
        /// </summary>
        [Description("The ultimate, above all, the best, top, something that nothing is better than")]
        Uber = 1,
        /// <summary>
        /// VSRE
        /// </summary>
        [Description("very short reply expected.")]
        Vsre,
        /// <summary>
        /// YOLO
        /// </summary>
        [Description("you only live once")]
        Yolo = 11
    }
}

在這個範例內,我設了一個 enum 叫做 Urban,裡面定義了若干資料,然後做了一些Demo。
enum


首先,我利用EnumToList這function把enum轉成IEnumerable,這樣才能用foreach把全部資料都拉出來。
然後我展示了enum間的比較,前面說過列舉原則上只能塞數字進去,所以Urban.L33T>Urban.Uber的比較其實就是 -1>1 ,結果當然會是False。
下一行是展示一下如何取得Description,雖然前面foreach內就有用過了。
最後是顯示一下enum的value是如何運作,enum不指值的話,預設是從0按順序加上去,所以Vrse從前值繼續往上加就是2。


簡單來說就是如此,試過就知道,其實這是個很方便的東西。

參考 : Associating Strings with enums in C#

No comments:

Post a Comment