專案剛好用到列舉型別(enum)的處理,之前雖已寫過一篇相關文章,但這次又多用到了找上下筆及列出清單的特性,索性再整理一篇更完整的。

以下示範列出所有列舉項目及對應數值、字串、整數與列舉間的雙向轉換寫法,還有尋找上一個、下一個列舉值的簡陋做法(很不嚴謹,僅為示意,想深入研究的人這裡有個LINQ範例可參考)。注意: 字串轉列舉無對應時會有Exception,數字轉列舉無對應值時不會出錯而是出現未列舉宣告值的數字。(列舉居然可以出現非預先設定範圍內的值,不就打破了其存在的意義? 這點始終讓我很狐疑)

using System;
 
public class CSharpLab
{
    public enum State
    {
        Init, Open, Proc, Close, Done = 9
    }
    public static void Test()
    {
        State st = State.Init;
        //列出所有名稱
        foreach (string en in Enum.GetNames(typeof(State)))
            Console.WriteLine("Enum Name: " + en);
        //列舉背後有值, 預設由零開始排, 但也可自訂
        //TIPS: typeof(State)與st.GetType()都可取得列舉型別
        foreach (int v in Enum.GetValues(st.GetType()))
            Console.WriteLine("Enum Value: " + v.ToString());
        //將列舉轉為字串
        Console.WriteLine("Enum To String: " + st.ToString());
        //將字串轉為列舉
        st = (State)Enum.Parse(typeof(State), "proc", true);
        Console.WriteLine("String To Enum: " + st);
        try {
            Console.WriteLine("String To Enum(not found): " + 
                                    Enum.Parse(typeof(State), "WTF"));
        } catch (Exception ex) {
            Console.WriteLine("Error when Enum.Parse: " + ex.Message);
        }
        //將列舉轉為數字
        Console.WriteLine("Enum to Int: " + st + " " + (int)st);
        //將數字轉回列舉
        st = (State)9;
        Console.WriteLine("Int to Enum: " + st);
        //小心數字轉換對不上時不會有錯誤,但會出現非列舉值
        st = (State)100;
        Console.WriteLine("Int(100) to Enum: " + st);
        //如果數字有連續,可以用+1, -1找上一個下一個
        //注意: 以下範例並未檢查邊界及數值不連續的狀況, 
        //並非嚴謹寫法,僅為簡單示意,勿用於正式用途
        st = State.Proc;
        State next = (State)((int)st)+1;
        State prev = (State)((int)st)-1;
        Console.WriteLine("Now = " + st + " Next = " + next + " Prev = " + prev);
    }
}
 

執行結果如下(以上程式可用Mini C# Lab直接執行),橘色為字串轉換無法對映的狀況,綠色為數字轉換無法對映的狀況。

Enum Name: Init
Enum Name: Open
Enum Name: Proc
Enum Name: Close
Enum Name: Done
Enum Value: 0
Enum Value: 1
Enum Value: 2
Enum Value: 3
Enum Value: 9
Enum To String: Init
String To Enum: Proc
Error when Enum.Parse: Requested value 'WTF' was not found.
Enum to Int: Proc 2
Int to Enum: Done
Int(100) to Enum: 100
Now = Proc Next = Close Prev = Open

最後補充一個用法,enum可以加上[Flags]宣告,再將各值設成0x01, 0x2, 0x4, 0x8...,就可以當成旗標用myFlags = MyEnum.Flag1 | MyEnum.Flag2的方式操作,myFlags.ToString()時會傳回Flag1, Flag2。MSDN上有完整的範例,這裡不再贅言。


Comments

# by 大估

大估會在Enum的列舉值中,加上Description,放入對應的字串 例子如下… Public Enum FlowSignAnser <Description("同意")> Yes = 0 <Description("不同意")> No = 1 End Enum 再用下面這個Function抓值 Public Function glb_GetEnumDescription(ByVal EnumConstant As [Enum]) As String Dim Fi As FieldInfo = EnumConstant.GetType().GetField(EnumConstant.ToString()) Dim DescAttr() As DescriptionAttribute = DirectCast(Fi.GetCustomAttributes(GetType(DescriptionAttribute), False), DescriptionAttribute()) If DescAttr.Length > 0 Then Return DescAttr(0).Description Else Return EnumConstant.ToString() End If End Function

# by Jeffrey

to 大估,這招不錯!! 我之前都得另外寫一個Mapper函數用switch case對照出各列舉的中文名稱。(筆記,沙沙沙...)

# by 小期

傳入整數不會出錯我想原因就是在旗標那部份 >> 最後補充一個用法,enum可以加上[Flags]宣告,再將各值設成0x01, 0x2, 0x4, 0x8...,就可以當成旗標用myFlags = MyEnum.Flag1 | MyEnum.Flag2的方式操作,myFlags.ToString()時會傳回Flag1, Flag2。MSDN上有完整的範例,這裡不再贅言。 因為們可以作以下的位元運算 MyEnum myFlags = MyEnum.Flag1 | MyEnum.Flag2 這樣他會得到結果 3 ,但 3 實際並不存在在 Enum 裡面,只是他同時代表著是 Flag1 及 Flag2 另外 Enum 其實他的型別預設就是 Integer ,所以他本來就可以存放 Integer 的任意數(在 VB.Net 宣告 Enum 後可以用 As 指定型態,目前手邊沒有 C# ,不確定 C# 是否相同!)

# by Jeffrey

to 小期,感謝你的補充。

Post a comment