枚舉類型(enumerated types)定義了一組"符號名稱/值"配對。
例如,以下Color類型定義了一組符號,每個符號都標識一種顏色:
Red, Green, Blue, Orange }
1)枚舉類型使程序更容易編寫、閱讀和維護。有了枚舉類型,符號名稱可在代碼中隨便使用,開發人員不需要記 住每個硬編碼的含義。而且,一旦與符號名稱對應的值發生變化,代碼也可以簡單的重新編譯,不需要對源代碼做出任何修改。除此之外,文檔工具和其他實用程序能向開發人員顯示有意義的符號名稱。
2)枚舉類型是強類型的。
在Microsoft .NET Framework中,枚舉類型不只是編譯器所關心的符號,它在類型系統中還具有"一等公民"的地 位,能實現非常強大的操作。
編譯枚舉類型時,C#編譯器會把每個符號轉換成為類型的一個常量字段。例如,編譯器會把前面的Color枚舉類型看成以下代碼:
Color While = (Color) Color Red = (Color) Color Green = (Color) Color Bule = (Color) Color Orange = (Color)
上述偽類型定義了解內部工作方式。簡單的說,枚舉類型只是一個結構,其中定義了一組常量字段和一個實例字 段。常量字段會嵌入程序集的元數據中,並可以通過反射來訪問。這意味著可以在運行時獲得與枚舉類型關聯的 所有符號及其值。還意味著可以將一個字符串符號轉換成對應的數值。這些操作是通過System.Enum基類型來提 供的,該類型提供了幾個靜態和實例方法,可利用它們操作枚舉類型的一個實例,從而避免了必須使用反射的麻
煩。
提示:枚舉類型定義的符號是常量值。所以當編譯器發現代碼引用了一個枚舉類型的符號,就會在編譯時用數值 替換符號,代碼將不再引用定義了符號的枚舉類型。這意味著在運行時可能不需要定義了枚舉類型的程序集,在
編譯時需要。
例如,System.Enum類型有一個GetUnderlyingType的靜態方法,而System.Type類型有一個 GetEnumUnderlyingType的實例方法。
Type GetUnderlyingType (Type enumType); Type GetEnumUnderlyingType (Type enumType);
short,ushort,int(最常用,也是C#默認的),uint,long,或ulong。雖然這些C#基元類型都有都有對象的FCL 類型,但C#編譯器為了簡化本身的實現,要求只能指定基元類型名稱。如果使用FCL類型名稱(如Int32),就會報
錯。
以下代碼演示了如何聲明一個基礎類型為byte(System.Byte)的枚舉類型:
inter Color :
Console.WriteLine(Enum.GetUnderlyingType((Color)));
所有這些操作符實際作用於枚舉類型實例內部的value__實例字段。此外,C#編譯器還運行將枚舉類型的實例顯式 的轉型為一個不通過的枚舉類型。也可以顯式將一個枚舉類型實例轉型為一個數值類型。
可以調用System.Enum的靜態方法GetValue或者System.Type的實例方法GetEnumValue獲取一個數組,該數組的每一個元素都對應枚舉類型中的一個符號名稱,每個元素都包含符號名稱的數值:
Array GetValues(Type enumType); Array GetEnumValues(Type enumType);
= (Color[])Enum.GetValues( + (Color color Console.WriteLine(
Number of symbols defined: 5
Value Symbol
----- ------
0 While
1 Red
2 Green
3 Blue
4 Orange
還有其他枚舉類型成員,就不一一敘述了!
程序員經常要與位標識(bit flag)集合打交道。調用System.IO.File類型的GetAttributes方法,會返回FileAttributes類型的一個實例。FileAttributes類型是基本類型為Int32的枚舉類型,其中每一位都反映了文件的一項屬性。FileAttibutes類型在FCL中的定義如下:
= = = Directory = = , Hidden = = = = = = = = = NET_4_5= =
String file ==,file,(attributes & FileAttributes.Hidden) !=);
File.SetAttributes(file,FileAttributes.ReadOnly | FileAttribute.Hidden);
定義用於標識位標志的枚舉類型時,當然應該顯式為每個符號分配一個數值。通常,每個符號都有單獨的一個位處於on(1)狀態.此外,經常都要定義一個值為0的None符號。還可以定義一些代表常用位組合的符號。另外,強烈建議向枚舉類型應用System.Flags.Attribute這個定制的attribute類型,如下所示
= = = Actions.Read |= = =
Actions actions = Actions.Read | Actions.Delete; Console.WriteLine(actions.ToString());
永遠不要對位標志枚舉類型使用IsDefined方法,理由如下:
1)如果向IsDefined方法傳遞一個字符串,它不會將這個字符串拆分為單獨的token來進行查找,而是視圖查找整個字符串,把它看成是包含逗號的一個更大的符號。由於不能在枚舉類型中定義含有逗號的符號,所以這個符號永遠找不到。
2)如果向IsDefined方法傳遞一個數值,它會檢查枚舉類型是否定義了一個其對應數值和傳入數值匹配的符號。由於位標志不能這樣簡單匹配,所以IsDefined通常會返回flase。
現在,可以使用C#的擴展方法功能向枚舉類型模擬添加方法。
如果想為FileAttributes枚舉類型添加一些方法,可以定義一個包含了擴展方法的靜態類,如下所示:
Boolean Set( flags |
FileAttributes fa == fa.Set(FileAttributes.ReadOnly);