首先看一看什麼是裝箱和拆箱?
簡單的來說:
裝箱就是實值型別轉換為參考型別;
拆箱就是參考型別轉換為實值型別。
實值型別,包括原類型(Sbyte、Byte、Short、Ushort、Int、Uint、Long、Ulong、Char、Float、Double、Bool、Decimal)、枚舉 (enum) 、結構 (struct)。
參考型別包括類、數組、介面、委託、字串等。
裝箱:實值型別到參考型別或到此實值型別所實現的任何介面類型的隱式轉換
例如: int temp = 3;
System.Object obj = temp;
其中,temp為實值型別,在棧中分配;當分配obj這個參考型別時,我們需要在堆中分配一個obj對象,然後把temp值賦給它,這麼一系列的過程就是裝箱的過程。
拆箱:從參考型別到任意實值型別的顯式轉換。與裝箱不同,拆箱式顯示轉換。
例如:int temp = 3;
System.Object obj = temp;
int i = (int) obj;
拆箱過程中,首先來確定對象obj為一個實值型別的裝箱值,然後把值賦給實值型別。
隱式轉換總會成功的情況,不會拋出異常:
(1)、從衍生類別到基類;
(2)、從派生介面到基底介面;
(3)、從類到介面(該類實現了介面);
(4)、從Null到任何類;
顯式引用轉換,以下可能拋出異常,轉換不一定成功:
(1)、從基類到衍生類別;
(2)、從介面到介面(基底介面到派生介面或者倆介面沒有關係);
(3)、從介面到類(該類實現了該介面或該類未封閉);
(4)、從類到介面(該類未實現該介面且該類未封閉);
上面簡單的介紹了拆箱和裝箱的定義,下面就來討論一下裝箱和拆箱與堆和棧怎樣使用
其中實值型別是在棧中分配記憶體,本身的聲明就是一個初始化的過程,其不需要進行記憶體回收,只要超出所定義的作用範圍會自動釋放記憶體,而參考型別則是在堆中分配的,和java一樣,在堆種分配記憶體,而其託管堆進行記憶體回收。當兩種資料類型進行轉換時就引出了裝箱/拆箱。
比較裝箱和拆箱的優缺點
裝箱和拆箱雖然滿足了兩隻類型之間的轉換。但是從裝箱的過程中不難看出,每次裝箱時要在堆中new一個新的對象,當量特別大是肯定會大大影響程式的效率。事物總有兩面性,every sword has two sides,事情便簡單了,效能也下來了。所以,在應用中,我們應該盡量避免裝箱操作。
瞭解了裝箱和拆箱的操作,我們可以清楚的明白:裝箱操作會導致資料在堆和棧上進行拷貝,頻繁的裝箱操作會效能損失。而相比而言拆箱過程對效能損耗還是比較小的。
裝箱和拆箱的詳細步驟
1、裝箱(box)的詳細步驟:
(1)、在堆上分配一個記憶體空間,大小等於需要裝箱的實值型別對象的大小加上兩個參考型別對象都擁有的成員:類型對象指標和同步區塊引述。
(2)、把堆棧上的實值型別對象複製到堆上新分配的對象。
(3)、返回一個指向堆上新對象的引用,並且儲存到堆棧上被裝箱的那個實值型別的對象裡。
這個步驟不需要程式員自己編寫,在任何出現裝箱的地方,編譯器會自動加上執行以上功能的IL代碼。
所謂的拆箱就是裝箱對應著的概念,但拆箱的過程和裝箱並不是倒過來就是:
2、拆箱(unbox.any)的詳細步驟
如果為待拆箱對象為null,拋出NullReferenceException異常。
如果引用指向的不是一個期望對象的已裝箱對象,拋出InvalidCastException異常。
(1)、擷取已裝箱對象中各個欄位的地址,這個過程就是“拆箱”
需要說明的是一般拆箱以後會伴隨著對象的拷貝,但拷貝操作已經不是拆箱的範疇。
下面舉兩個小的例子來實現什麼是裝箱、拆箱以及怎樣避免因頻繁的裝箱而耗費記憶體
(1)、裝箱:
using System; public class Test { public static void Main(String[] args) { int i = 10; //將實值型別的i裝箱 //需要注意的是:這裡的裝箱採用的是值的拷貝 object obj = i; //檢驗是否裝箱成功了 if(obj is int) { Console.WriteLine("資料已經裝箱!"); } //我們在這裡更改i的值 i = 33; Console.WriteLine("int i現在的值是:{0}",i); Console.WriteLine("int i裝箱的值是:{0}",obj); } }
(2)、拆箱:
int i = 10; object obj = i; int j = (int)obj; (3)、避免頻繁的裝箱: int i = 10; int j = 20; int s = 30; Console.WriteLine("i的值為{0},j的值為{1},s的值為{2}", i.ToString(), j.ToString(), s.ToString());
以上就是介紹了C#的裝箱與拆箱,思路很清晰,涉及的內容很全面,包括裝箱和拆箱的優缺點、裝箱和拆箱的步驟等,很適合初學者進行學習。