12.1 枚舉類型
強類型,枚舉之間進行不能隱式轉換
枚舉類型直接派生於System.Enum,後者派生於System.ValueType,值類型,可以使用裝箱/拆箱
不能定義方法/屬性/事件。
同一個枚舉中,多個枚舉符號有相同的數值,數值轉符號時,會返回其中第一個符號。
枚舉類型要與使用它的類在同一級。
默認為int,可以指定枚舉成員的類型,只有int,uint,byte,sbyte,long,ulong,short,ushort 這8種基元類型。
可以使用操作符作用於枚舉類型,實際上是作用於相應的value實例字段,如++。
可以將枚舉類型的實例顯示轉型為另一個不同的枚舉類型,其實是先轉為值,再反過去在另一個枚舉 中根據值找對應枚舉值。
可以顯示將枚舉類型的實例轉型為一個數值類型。
public enum Color { Red, Black, White } public enum Sentence { hello, bye } class Program { static void Main(string[] args) { //使用運算符,++ Color a = Color.Red; ++a; Sentence s; //兩個不同的枚舉相互轉換, 但是發現Color.White值為2,相應在Sentence中找 不到,所以直接返回整數2 s = (Sentence)Color.White; //等價於(Sentence)1; //兩個不同的枚舉相互轉換,返回枚舉值Black s = (Sentence)Color.Black; //直接輸出White枚舉值, 顯式轉為整數 Console.WriteLine(Color.White); //輸出white Console.WriteLine((Int32)Color.White); //輸出2 } }
如 enum Color{Red=1, White=2}對應IL:
可以看到,枚舉只是一個在其中定義一系列常量字段和實例字段的結構。
如果只使用Color.Red這樣的類型,則會作為常量處理,從而代碼不再引用定義了的枚舉類型,可以刪 除相應的dll(具體見第7章);
如果使用Color c = new Color();這樣的語法,那麼依賴於引用,不可以刪除相應的dll
枚舉方法列表:
1.GetUnderlyingType靜態方法,獲取枚舉類型值的核心類型:
//返回System.Int Enum.GetUnderlyingType(typeof(Color));
2.ToString()方法
Color c = Color.Black; Console.WriteLine(c); //輸出Black Console.WriteLine(c.ToString()); //輸出Black Console.WriteLine(c.ToString("G")); //輸出Black,以上都是泛型 格式 Console.WriteLine(c.ToString("D")); //輸出1,十進制 Console.WriteLine(c.ToString("X")); //輸出00000001,十六進制
對於c.ToString("X")十六進制格式,A-F始終是大寫字母。此外,輸出的數位個數取決於Color的基本 類型:
byte/sbyte 2位 short/ushort 4位 int/uint 8位 long/ulong 16位
3.Format靜態方法,功能基本同ToString()方法,但允許value傳遞一個數值,而不僅僅是一個Enum類 型
Enum.Format(typeof(Color), 3, "G");
4.GetValues靜態方法,返回一個數組,數組中為所有的枚舉類型名稱:
Color[] colors = (Color[])Enum.GetValues(typeof(Color));
5.static String GetName(Type enumType, Objbect value)靜態方法,返回數值的字符串表示
6.static String[] GetNames(Type enumType),返回方法5的數組表示
7.Parse靜態方法,將一個符號轉換為枚舉類型的一個實例:
Color cc1 = (Color)Enum.Parse(typeof(Color), "2"); Color cc2 = (Color)Enum.Parse(typeof(Color), "Black"); //可以是值,也可以是枚舉類型名稱 Color cc3 = (Color)Enum.Parse(typeof(Color), "Black", true); //可 選參數true表示忽略大小寫
8.IsDefined靜態方法,判斷一個數值對於一個枚舉類型是否合法:
Enum.IsDefined(typeof(Color), 10); //返回false,Color中沒有10 Enum.IsDefined(typeof(Color), "Black"); //返回true
常用於參數驗證:
public void SetColor(Color c) { if (!Enum.IsDefined(typeof(Color), c)) { //拋出異常,c不適合Color } }
注:Enum.IsDefined方法慎用,因為要區分大小寫查找;使用反射機制,速度慢。
9.ToObject靜態方法,一系列方法,如Enum.ToObject (Type, Byte),將Int32,Byte等類型實例轉為 枚舉類型的實例(由於返回都是Object,所以要顯示轉型)
12.2 位標志 bit flag
位標志是一個位集合,其中有些位on,有些位off;而枚舉是一個數值,是位集合中若干值的累加。
在枚舉上應用[Flags]屬性,就可以用枚舉來表示一組可以組合的位標志,一般要定義一個值為0的 None符號。
[Flags] public enum FileAttributes { ReadOnly = 0x0001, Hidden = 0x0002, System = 0x0004 }
這時,就可以使用位運算來操作:
邏輯與,判斷是否有這個枚舉值
//以下代碼,先取出文件的屬性列表——是一個位集合, //與FileAttributes.Hidden做邏輯:如果位集合中有FileAttributes.Hidden,則返回 FileAttributes.Hidden String file = @"C:\Boot.ini"; FileAttributes attributes = File.GetAttributes(file); if ((attributes & FileAttributes.Hidden) == FileAttributes.Hidden) { }
邏輯或,組合出所需的枚舉列表,一般用來設置:
File.SetAttributes(path, FileAttributes.ReadOnly | FileAttributes.Hidden);
對位標記Enum調用ToString()方法,數值轉字符串:
先檢查是否應用了[Flags]屬性
如果沒有,就查找與該數值匹配的Enum符號並返回,沒有匹配就返回數值。
如果有,就獲取Enum降序排列的數值集合A,將A中的數值“按位與”Enum實例中的數值,將結果等於 數值的Enum項附加到輸出字符串,以逗號分割,如"Read,Write"
有兩種特殊情況:
1.一個數值不能由Enum的若干項組合,則返回該數值
2.應該定義0。
對位標記Enum調用Parse()方法,字符串轉數值:
Enum.Parse(typeof(Color), "Query"); Enum.Parse(typeof(Color), "Query, Read"); Enum.Parse(typeof(Color), "28");
處理過程如下:
1.刪除字符串中所有空白字符
2.如果字符串以+/-/數字開始,那麼字符串被認為是一個數字,直接轉型為對應數值的字符串
3.以逗號分割字符串,在Enum中查找相應符號的數值,按位或取值並返回
不要對位標記Enum調用IsDefined()方法,因為,
傳字符串,位標記中含有逗號,但永遠找不到含有逗號的枚舉符號;
傳數值,永遠返回false