第 47 講:枚舉(三):其它枚舉相關(guān)的問(wèn)題
前面已經(jīng)說(shuō)過(guò)了枚舉的基本使用方式,以及運(yùn)算符的使用。下面講一些有關(guān)枚舉類型的、前面沒(méi)有提到的問(wèn)題。
Part 1 枚舉字段是否定義的問(wèn)題
我們經(jīng)常使用枚舉類型把數(shù)值取出。但問(wèn)題是,前文我們?cè)诒磉_(dá)枚舉類型和整數(shù)類型進(jìn)行互相轉(zhuǎn)換的時(shí)候,尚未提及整個(gè)問(wèn)題,那就是:如果我們將一個(gè)不存在于枚舉類型里的特征值強(qiáng)制轉(zhuǎn)換為枚舉類型,那么使用它是成功的嗎?是拋異常呢,還是其它情況呢?
假設(shè)我有一個(gè)枚舉類型,只包含兩個(gè)數(shù)值:
Gender
實(shí)際上,沒(méi)有任何事發(fā)生。賦值是成功的,也不會(huì)有異常,也不會(huì)中斷程序,更不會(huì)出現(xiàn)別的現(xiàn)象。這樣的賦值唯一和正常范圍的特征值表現(xiàn)出來(lái)效果不一樣的地方是調(diào)用 ToString
方法之后。
前者的 0 特征值對(duì)應(yīng)了 Gender
類型的 Male
,因此這么轉(zhuǎn)換最后輸出的是 Male
也就是說(shuō),如果對(duì)于一個(gè)沒(méi)有對(duì)應(yīng)字段的枚舉類型變量進(jìn)行 ToString
輸出的話,實(shí)際上輸出的是特征值本身;如果有的話,實(shí)際上輸出的就是這個(gè)字段的名字。這是兩種情況的不同點(diǎn),其它的使用完全都是一樣的,不會(huì)因?yàn)槌雒杜e定義范圍而直接告訴你不能這么用,C# 沒(méi)有必要限制得這么死,畢竟……沒(méi)定義又不是什么無(wú)傷大雅的事情。
Part 2 特征值表達(dá)式
前文我們學(xué)習(xí)了如何使用位運(yùn)算來(lái)對(duì)特殊的枚舉類型進(jìn)行操作。不過(guò),實(shí)際上 C# 甚至允許你直接在特征值賦值的時(shí)候書(shū)寫(xiě)表達(dá)式。比如這樣:
不過(guò)這里稍微注意一點(diǎn)。我們之前說(shuō)過(guò),<<
和 >>
是枚舉類型無(wú)法使用的運(yùn)算符,但是在特征值賦值的表達(dá)式里,我們可以用,但右側(cè)必須是一個(gè) int
類型的字面量。
比如這樣的枚舉,每一個(gè)字段都是前一個(gè)字段的特征值的兩倍。
但是我們?cè)谄綍r(shí)使用的時(shí)候,我們無(wú)法使用 <<
運(yùn)算符,因?yàn)檫@是 C# 規(guī)定禁止使用的、為數(shù)不多的運(yùn)算符之一:
Part 3 負(fù)數(shù)特征值的枚舉轉(zhuǎn)換
可能你使用過(guò)帶符號(hào)類型的整數(shù)作為特征值的基本類型表示在枚舉類型的“繼承關(guān)系”上。實(shí)際上,默認(rèn)情況下枚舉類型是使用 int
這個(gè)帶符號(hào)的類型作為特征值類型的。
那么,如果我賦值 -1 作為某字段的特征值的話,我要想使用它,你可能會(huì)這么寫(xiě)代碼:
TestEnum
另外在 C# 的字面量系統(tǒng)里,數(shù)據(jù)使用字面量有很復(fù)雜的轉(zhuǎn)換關(guān)系(什么“不超過(guò)一定范圍的字面量,雖然是 int
類型也可以表示為較小數(shù)據(jù)類型”之類的規(guī)則)。正是因?yàn)檫@些規(guī)則的約束,一旦放開(kāi) -1 不添加括號(hào)直接轉(zhuǎn)換的話,就會(huì)和這些細(xì)節(jié)產(chǎn)生一定的語(yǔ)義沖突。為了避免這一點(diǎn),C# 不得不讓你添加這個(gè)小括號(hào),告訴你要想是負(fù)數(shù)枚舉特征值的話,就必須加了小括號(hào)后再來(lái)強(qiáng)制轉(zhuǎn)換。