有關C 列舉的問答集錦 基礎篇

2021-05-23 01:26:08 字數 3858 閱讀 9285

q:在c#裡,我們如何表達列舉型別?

a:你可以使用enum關鍵字(keyword)來宣告乙個列舉型別(enum type):

// code #01 

public

enumalignment  

q:c#列舉型別是值型別(value type)還是引用型別(reference type)?

a:列舉型別都是值型別。

q:system.enum是列舉型別麼?

a:不是。

q:system.enum與列舉型別(enum type)有什麼關係?

a:system.enum是乙個抽象類(abstract class),所有列舉型別都直接繼承自它,當然也同時繼承了它的所有成員。

q:那麼system.enum屬於引用型別啦?

a:是的。

q:既然system.enum是引用型別,而列舉型別又是直接繼承自system.enum的,那為什麼列舉型別卻不是引用型別?

a:這種繼承關係是隱式的並由編譯器負責展開,上面code #1的alignment列舉被展開後的il**如下:

// code #02 

.class

publicauto ansisealedaligment  

extends [mscorlib]system.enum  

從宣告中,你可以看到aligment的確是繼承自system.enum的,只是你不能在c#裡顯式宣告這種繼承關係。

q:但你好像沒有回答為什麼列舉型別繼承自乙個引用型別後,卻還是值型別!

a:你知道,所有的值型別都是system.valuetype的後代,列舉型別也不例外,列舉型別直接繼承自system.enum,而system.enum卻又直接繼承自system.valuetype的,所以,列舉型別也是system.valuetype的後代。

q:慢著!從system.valuetype派生出來的型別不都應該是值型別嗎?為什麼system.enum會是引用型別?

a:正確的說法應該是「值型別都是system.valuetype的後代」,但system.valuetype的後代不全是值型別,system.enum就是唯一的特例!在system.valuetype的所有後代中,除了system.enum之外其它都是值型別。事實上,我們可以在.net的源**中找到system.enum的宣告:

public

abstract

classenum : valuetype, icomparable, iformattable, iconvertible  

請注意,.net framework sdk v2.0.3600.0 documentation中的enum宣告是錯的:

public abstract struct enum : icomparable, iformattable, iconvertible

q:開始頭暈了,究竟c#列舉型別、system.enum、system.valuetype、值型別和引用型別之間存在著什麼樣的關係?

a:簡單的說,

1. 所有列舉型別(enum type)都是值型別。

2. system.enum和system.valuetype本身是引用型別。

3. 列舉型別(enum type)都是隱式的直接繼承自system.enum,並且這種繼承關係只能由編譯器自動展開。但system.enum本身不是列舉型別(enum type)。

4. system.enum是乙個特例,它直接繼承自system.valuetype(參見code #03),但本身卻是乙個引用型別。

好吧,現在來看看下面**,你能猜得出它的輸出結果嗎?

// code #04 

static

voidmain()  

請別驚訝於程式的執行結果沒有任何輸出!對於第乙個判斷,我們很清楚system.enum並不是列舉型別。但第二個判斷呢?system.enum明明繼承自system.valuetype,卻不承認是system.valuetype的後代!這是.net上的乙個特例,恰恰體現出system.enum是特殊性。

q:既然列舉型別是值型別,自然會涉及到裝箱和拆箱(boxing and unboxing)的問題,那麼列舉型別會被裝箱成什麼呢?[updated]

a:列舉型別可以被裝箱成system.enum、system.valuetype、system.object或者system.iconvertible、system.iformattable、system.icomparable。

注意:在.net 1.1上,列舉型別只能被裝箱到system.enum、system.valuetype、system.object;而在.net 2.0上,列舉型別還能被裝箱到system.enum所實現的三個介面:system.iconvertible、system.icomparable、system.iformattable。對應的裝箱操作既可以為隱式的也可以是顯式的。

下面的c#**:

// code #05 

// see code #01 for alignment.

static

voidmain()  

對應的il**是:

// code #06 

.methodprivatehidebysigstatic

voidmain() cil managed  

從il**中我們可以看到列舉型別被裝箱兩次。第一次(l_0003)被裝箱成system.enum,而第二次(l_0014)就被裝箱成system.object。

但如果你讓編譯器自動為你選擇裝箱型別的話,它會優先考慮system.enum:

// code #07 

// see code #01 for alignment.

classprogram  

static

voidprint(iconvertible c)  

static

voidprint(iformattable f)  

static

voidprint(icomparable c)  

static

voidprint(object o)  

static

voidprint(valuetype v)  

static

voidprint(enum e)  

}  

上面的**將被編譯成如下的il:

// code #08 

.methodprivatehidebysigstatic

voidmain(stringargs) cil managed  

關於蘋果iPhone的FAQ使用問答集錦

iphone問答 如何用iphone打 要用iphone打 你先按home鍵進入主選單,在左下角有乙個 的圖示,用你的手指輕輕觸控它啟動iphone的 功能,在螢幕的虛擬鍵盤上輸入 號碼,或者從你的聯絡人列表 收藏或是呼叫記錄中選取。iphone的螢幕多大 iphone的螢幕是一塊3.5英吋,160...

怎麼畫六面體網格 網格劃分的問答集錦

網格劃分就是把模型分成很多小的單元,作為有限元分析前處理的重中之重,網格劃分與計算目標的匹配程度 網格的 壞,決定了後期有限元計算的質量。1 有限元分析為什麼要進行網格劃分?是為了使模型變成有限元,劃分網格之後,單元節點的位移增量是有限元迭代過程中的基本未知量。有限元網格劃分是進行有限元數值模擬分析...

c 列舉基礎 與 列舉屬性的訪問

列舉提供成組的常數值,它們有助於使成員成為強型別以及提高 的可讀性。在 c 中,使用 enum 來宣告列舉。列舉分為簡單列舉和標誌列舉兩種。基本語法示例 enum day 以下格式也可以 enum day 列舉型別 列舉型別可以是 byte sbyte short ushort int uint l...