.NET中的枚举(Enum)
摘要:.NET中的枚舉分為簡(jiǎn)單枚舉和標(biāo)志枚舉,這次主要總結(jié)一下標(biāo)志枚舉適用條件,以及它的使用方法,并在文章的最后列舉枚舉使用的一些規(guī)范。
在剛接觸.NET的枚舉時(shí),只用簡(jiǎn)單的枚舉,對(duì)于標(biāo)記枚舉,只知道是在枚舉類型加上Flags特性,然后給枚舉值賦予十六進(jìn)制的值,并且書(shū)中還特別明確規(guī)定值必須是以2的指數(shù)才可以,這樣可以方便在使用時(shí),對(duì)多個(gè)枚舉值進(jìn)行或運(yùn)算。隨著對(duì).NET的了解不斷的深入,現(xiàn)在終于明白了標(biāo)志枚舉的適用場(chǎng)合以及它的使用方法,因此在這里總結(jié)一下。
標(biāo)志枚舉的適用條件
在System.Drawing命令空間中有一個(gè)FontStyle標(biāo)志枚舉,專門用來(lái)設(shè)置字體的風(fēng)格,有Blod、Italic、Regular、Strikeout、Underline這5種風(fēng)格。當(dāng)然我們需要設(shè)置字體為單個(gè)一種風(fēng)格時(shí),那么FontStyle枚舉的用法和簡(jiǎn)單枚舉沒(méi)什么區(qū)別,比如,我們需要把字體風(fēng)格為設(shè)置為粗體,代碼如下:
System.Drawing.Font font = new System.Drawing.Font("宋體",12,FontStyle.Bold);但是,如果我們需要設(shè)置字體的風(fēng)格為粗體的同時(shí)還要需要斜體和下劃線呢?對(duì)于這種情況,簡(jiǎn)單枚舉就不適用了,這就必須使用標(biāo)志枚舉的進(jìn)行組合才能辦到了,代碼如下:
System.Drawing.Font font = new System.Drawing.Font("宋體",12, FontStyle.Bold|FontStyle.Italic|FontStyle.Underline);通過(guò)這樣的組合就能夠達(dá)到我們想要的效果。
自定義FontStyle標(biāo)志枚舉,一探究竟
下面我們自己設(shè)計(jì)一個(gè)FontStyle,看看它的內(nèi)部是如何實(shí)現(xiàn)的。代碼如下:
[Flags] public enum FontStyle: byte { Bold=0x01,Italic = 0x02,Regular = 0x04,Strikeout=0x08,Underline=0x10, }上面的定義了一個(gè)FontStyle枚舉,該枚舉繼承byte類型,通過(guò)加上Flags特性,使它成為標(biāo)志枚舉,并且為每一個(gè)枚舉值賦值一個(gè)十六進(jìn)制的值,每一個(gè)值都是2的指數(shù)值。下面將詳細(xì)解釋一些為什么要使用2的指數(shù)來(lái)進(jìn)行賦值。
為什么使用2的指數(shù)值對(duì)枚舉進(jìn)行賦值
首先我們要明白,二進(jìn)制的或運(yùn)算,或運(yùn)行無(wú)非就4種情況,
0|0=0; 0|1=1; 1|0=1; 1|1=1;那么二進(jìn)制10101010和01010101進(jìn)行或運(yùn)算就等于11111111,明白了二進(jìn)制的或運(yùn)算,再仔細(xì)想想,一個(gè)字節(jié)8位二進(jìn)制,可以代表0-255。其中1,2,4,8,16,32,64,128是2的指數(shù),分別代表的二進(jìn)制的00000001,00000010,00000100,00001000,00010000,00100000,01000000,10000000,它們的每個(gè)取值剛好是將8位中的某一位設(shè)為1。那么這8個(gè)值以及它們?nèi)我饨M合(或運(yùn)算)剛好能夠代表$C^1_8+C^2_8+C^3_8+C^4_8+C^5_8+C^6_8+C^7_8+C^8_8=255 $種情況(其中$C_8^1?$是單個(gè)枚舉,其他都是組合),對(duì)標(biāo)志枚舉使用2的指數(shù)值進(jìn)行賦值,能夠進(jìn)行任意的組合,并且任意組合后的值不會(huì)有重復(fù)。這就是為什么要使用2的指數(shù)值對(duì)標(biāo)志枚舉進(jìn)行復(fù)制的原因。順便這里再多說(shuō)一句,賦值的時(shí)候?yàn)槭裁床挥?0進(jìn)制,而是用16進(jìn)制的表示法,前面我們分析了,標(biāo)志枚舉的組合最后都將進(jìn)行二進(jìn)制的或運(yùn)算,而我們?cè)谫x值的時(shí)候用16進(jìn)制會(huì)更加表現(xiàn)明顯,因?yàn)槊恳粋€(gè)16進(jìn)制的數(shù)值,剛好代表二進(jìn)制4個(gè)位,所以兩個(gè)16進(jìn)制的數(shù)就能代表一個(gè)字節(jié),比如0x11,我們化為二進(jìn)制,只需要對(duì)兩個(gè)1分別換算4個(gè)二進(jìn)制位就行了,1=0001,所以0x11就代表00010001,如果用十進(jìn)制17來(lái)表示,就沒(méi)那么輕易地看出它的二進(jìn)制表示。
如何處理組合枚舉
當(dāng)我們把標(biāo)志枚舉賦值為2的指數(shù)值之后,我們就可以組合的使用這些枚舉值,以期達(dá)到我們想要的效果,那么在函數(shù)設(shè)計(jì)中,我們是如何來(lái)處理傳入進(jìn)來(lái)的枚舉組合值呢?其實(shí)也非常簡(jiǎn)單,正是因?yàn)樗麄內(nèi)我獾慕M合都不會(huì)重復(fù),因此每一個(gè)數(shù)值可以代表其中的一個(gè)枚舉值或者是一個(gè)組合,比如,FontStyle.Bold|FontStyle.Italic|FontStyle.Underline這個(gè)組合所代表的數(shù)值就位0x01|0x02|0x10=19.
下面設(shè)計(jì)一個(gè)函數(shù)處理傳入進(jìn)來(lái)的枚舉值。代碼如下:
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} }因?yàn)槊杜e在CLR內(nèi)部實(shí)現(xiàn)可以看做是數(shù)值類型。在Test函數(shù)內(nèi)部我們需要用Switch去判斷傳入的枚舉值,確定是否單個(gè)枚舉還是組合后的值,并對(duì)其做出相應(yīng)的處理。下面給出測(cè)試代碼。
static void Main(string[] args) {Test(FontStyle.Bold);Test(FontStyle.Strikeout|FontStyle.Italic);Test(FontStyle.Bold|FontStyle.Italic|FontStyle.Underline);Console.ReadKey();}測(cè)試結(jié)果如下:
總結(jié)一些設(shè)計(jì)枚舉的規(guī)范
- 簡(jiǎn)單枚舉的命名采用單數(shù)形式。
- 不要使用Enum、Flag、Flags作為枚舉類型的后綴。
- 不要給枚舉值的命名加上枚舉類型名前綴,比如FontStyleBlod這樣是不規(guī)范的。
- 使用枚舉代替一些固定的常量集合。
- 使用枚舉作為參數(shù)、屬性、返回值,來(lái)保證該API是強(qiáng)類型的API。
- 考慮給枚舉提供一個(gè)None=0的枚舉值。
- 給標(biāo)志枚舉賦值為2的指數(shù)值。
轉(zhuǎn)載于:https://www.cnblogs.com/mingjiatang/p/5947335.html
總結(jié)
以上是生活随笔為你收集整理的.NET中的枚举(Enum)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: mysql中如何把字符串转换成日期类型
- 下一篇: 详解.NET中容易混淆的委托与接口