在C#中,相信大家對於 "值類型" 並不陌生,因為它在我們代碼設計中是不可缺少的,那麼究竟什麼是 "值類型" 呢? "值類型"就是 我們用到的 Int16,Int32這些數值類型嗎?
我們知道在C#中所有的類型繼承於System.Object根類型,這也就意味著就代碼層面來講,在C#中所有的類型都是Class,,即一切都是Class類型,既然全部都是Class類型,那麼值類型在哪裡呢?我們可以發現在C#中System.Int16,System.Int32,System.Boolean...等等這些常用的類型都是Struct 結構類型,那麼結構類型是什麼,下面我們定義一個結構,然後通過IL Disassemble 工具來查看編譯的中間代碼便可以得到結果.
public struct CustomerStruct
{
public string Name{get;set;}
}
代碼非常簡單,我們就定義一個struct類型,並且包含一個Name屬性.
看到上面這幅圖,相信大家都已經看到定義一個struct類型實際上編譯把你所定義的類型繼承了System.ValueType類型,換句話說,在C#中我們經常使用的System.Int16,System.Int32,System.Boolean..這些數值結構類型都是繼承於System.ValueType類型,而System.ValueType又是繼承於System.Object根類型,即驗證我開始所講到的在C#中一切類型都是Class。
之所以存在"值類型" 這個概念,其實是因為C#中的某些類型有這特殊的地位(即繼承於System.ValueType的類型),CLR會特殊的對待這些類型,
看下面這2行代碼
Int32 a = new System.Int32(10) ;
CustomerStruct customer = new CustomerStruct() ;
首先為什麼對於數值類型也可以使用 new 來進行內存分配呢? 上面已經講到,因為他們都是Class類型,當然可以使用new 來進行內存分配.
其次,CLR執行這樣的代碼的時,CLR 通過反射(有待考察)或者其他途徑來獲知所要請求分配內存的類型是否繼承於System.ValueType如果是的話,那麼就在棧上進行分配,如果不是的話,那麼就是我們所說的引用類型,就在托管堆上分配內存以及棧上分配對應的引用變量,這些一切都是CLR做的工作.
我們再來看看裝箱操作.
object o = new object();
Int32 aaa = 100;
o = aaa; //這裡會發生裝箱操作
我們都知道當CLR執行到 o = aaa;這條語句時會發生裝箱操作,為什麼會發生裝箱操作呢?這是因為CLR 知道引用變量o所要引用的類型aaa是繼承於System.ValueType類型的,繼承於System.ValueType的類型都是在棧上分配的,而其它則是在托管堆上分配的,所以會CLR會弄得aaa的副本弄到托管堆上去,這一切也都是CLR的工作.
由此我們可以得出結論:
1.在C#中 就代碼層面上講 所有的類型都是Class類型.
2.所謂的 "值類型" != 數值類型,而是所有繼承於System.ValueType 的類型.
3."值類型" 得到的語言級別的支持,CLR知道如何對 "值類型" 這樣的Class類型進行內存分配和處理.
綜上所述.個人愚見,有什麼不對的地方希望大家幫忙指出,共同學習,共同進步.