摘要:.NET中的枚舉分為簡單枚舉和標志枚舉,這次主要總結一下標志枚舉適用條件,以及它的使用方法,並在文章的最後列舉枚舉使用的一些規范。
在剛接觸.NET的枚舉時,只用簡單的枚舉,對於標記枚舉,只知道是在枚舉類型加上Flags
特性,然後給枚舉值賦予十六進制的值,並且書中還特別明確規定值必須是以2的指數才可以,這樣可以方便在使用時,對多個枚舉值進行或運算。隨著對.NET的了解不斷的深入,現在終於明白了標志枚舉的適用場合以及它的使用方法,因此在這裡總結一下。
在System.Drawing
命令空間中有一個FontStyle
標志枚舉,專門用來設置字體的風格,有Blod、Italic、Regular、Strikeout、Underline這5種風格。當然我們需要設置字體為單個一種風格時,那麼FontStyle枚舉的用法和簡單枚舉沒什麼區別,比如,我們需要把字體風格為設置為粗體,代碼如下:
System.Drawing.Font font = new System.Drawing.Font("宋體",12,FontStyle.Bold);
但是,如果我們需要設置字體的風格為粗體的同時還要需要斜體和下劃線呢?對於這種情況,簡單枚舉就不適用了,這就必須使用標志枚舉的進行組合才能辦到了,代碼如下:
System.Drawing.Font font = new System.Drawing.Font("宋體",12, FontStyle.Bold|FontStyle.Italic|FontStyle.Underline);
通過這樣的組合就能夠達到我們想要的效果。
下面我們自己設計一個FontStyle
,看看它的內部是如何實現的。代碼如下:
[Flags]
public enum FontStyle: byte
{
Bold=0x01,
Italic = 0x02,
Regular = 0x04,
Strikeout=0x08,
Underline=0x10,
}
上面的定義了一個FontStyle
枚舉,該枚舉繼承byte
類型,通過加上Flags
特性,使它成為標志枚舉,並且為每一個枚舉值賦值一個十六進制的值,每一個值都是2的指數值。下面將詳細解釋一些為什麼要使用2的指數來進行賦值。
首先我們要明白,二進制的或運算,或運行無非就4種情況,
0|0=0; 0|1=1; 1|0=1; 1|1=1;
那麼二進制10101010和01010101進行或運算就等於11111111,明白了二進制的或運算,再仔細想想,一個字節8位二進制,可以代表0-255。其中1,2,4,8,16,32,64,128是2的指數,分別代表的二進制的00000001,00000010,00000100,00001000,00010000,00100000,01000000,10000000,它們的每個取值剛好是將8位中的某一位設為1。那麼這8個值以及它們任意組合(或運算)剛好能夠代表種情況(其中是單個枚舉,其他都是組合),對標志枚舉使用2的指數值進行賦值,能夠進行任意的組合,並且任意組合後的值不會有重復。
這就是為什麼要使用2的指數值對標志枚舉進行復制的原因。順便這裡再多說一句,賦值的時候為什麼不用10進制,而是用16進制的表示法,前面我們分析了,標志枚舉的組合最後都將進行二進制的或運算,而我們在賦值的時候用16進制會更加表現明顯,因為每一個16進制的數值,剛好代表二進制4個位,所以兩個16進制的數就能代表一個字節,比如0x11,我們化為二進制,只需要對兩個1分別換算4個二進制位就行了,1=0001,所以0x11就代表00010001,如果用十進制17來表示,就沒那麼輕易地看出它的二進制表示。
當我們把標志枚舉賦值為2的指數值之後,我們就可以組合的使用這些枚舉值,以期達到我們想要的效果,那麼在函數設計中,我們是如何來處理傳入進來的枚舉組合值呢?其實也非常簡單,正是因為他們任意的組合都不會重復,因此每一個數值可以代表其中的一個枚舉值或者是一個組合,比如,FontStyle.Bold|FontStyle.Italic|FontStyle.Underline
這個組合所代表的數值就位0x01|0x02|0x10=19.
下面設計一個函數處理傳入進來的枚舉值。代碼如下:
static void Test(FontStyle fontStyle)
{
switch ((byte)fontStyle)
{
case 1:
Console.WriteLine("Bold");
break;
case 2:
Console.WriteLine("Italic");
break;
case 3:
Console.WriteLine("Bold&Italic");
break;
case 4:
Console.WriteLine("Regular");
break;
case 6:
Console.WriteLine("Regular&Italic");
break;
case 8:
Console.WriteLine("Strikeout");
break;
case 9:
Console.WriteLine("Strikeout&Bold");
break;
case 10:
Console.WriteLine("Strikeout&Italic");
break;
case 11:
Console.WriteLine("Strikeout&Italic&Bold");
break;
case 16:
Console.WriteLine("Underline");
break;
case 19:
Console.WriteLine("Bold&Italic&Underline");
break;
//else
}
}
因為枚舉在CLR內部實現可以看做是數值類型。在Test函數內部我們需要用Switch去判斷傳入的枚舉值,確定是否單個枚舉還是組合後的值,並對其做出相應的處理。下面給出測試代碼。
static void Main(string[] args)
{
Test(FontStyle.Bold);
Test(FontStyle.Strikeout|FontStyle.Italic);
Test(FontStyle.Bold|FontStyle.Italic|FontStyle.Underline);
Console.ReadKey();
}
測試結果如下:
FontStyleBlod
這樣是不規范的。None=0
的枚舉值。