文章來自微軟官網: http://msdn.microsoft.com/zh-cn/library/yz2be5wk.aspx函數
裝箱是將值類型轉換爲object類型或由此值類型實現的任何接口類型的過程。當CLR對值類型進行裝箱時,會將該值包裝到System.Object內部,再將後者存儲在託管堆上。取消裝箱將從對象中提取值類型。性能
裝箱是隱式的;取消裝箱是顯示的。優化
裝箱和取消裝箱的概念是類型系統C#統一視圖的基礎,其中任一類型的值都被視爲一個對象。spa
在下面的示例中,將整型變量i進行了裝箱並分配給對象o。code
int i = 123; object o = i; // 將i裝箱
上述語句的結果是在堆棧上建立對象引用o,而在堆上則引用int類型的值。該值是賦給變量i的值類型的一個副本。下圖說明了兩個變量i和o之間的差別。對象
還能夠像下面的示例同樣執行顯式裝箱,但顯式裝箱歷來不是必須的:blog
int i = 123; object o = (object) i; // 顯式裝箱
而後,能夠將對象o取消裝箱並分配給整型變量i:接口
o = 123; i = (int)o; // 取消裝箱
取消裝箱操做包括兩個步驟:get
1. 檢查對象實例,以確保它是給定值類型的裝箱值。編譯器
2. 將該值從實例複製到值類型變量中。
下面的語句演示裝箱和取消裝箱兩種操做:
int i = 123; // 值類型 object o = i; // 裝箱 int j = (int)o; // 取消裝箱
下圖演示上述語句的結果。
取消裝箱轉換
要在運行時成功取消裝箱值類型,被取消裝箱的項必須是對一個對象的引用,該對象是先前經過裝箱該值類型的實例建立的。嘗試取消裝箱null會致使NullReferenceException。嘗試取消裝箱對不兼容值類型的引用會致使InvalidCastException。
如下示例演示如何在C#中使用裝箱。
// String.Concat 示例. // String.Concat 函數有不少版本,下面這個版本的函數的3個參數 // 都必須爲Object對象類型,因此 42 和 true 都將被裝箱。 Console.WriteLine(String.Concat("Answer", 42, true));
裝箱性能相關(以Unity中Debug.Log(object)函數爲例)
考慮一種基本的裝箱狀況,當使用Debug.Log(object)函數時,函數的參數類型爲object,也就意味着任何類型的變量都能傳遞給這個函數。例如當咱們傳遞一個整數的時候,編譯器將會對傳遞進來的整數進行裝箱操做使其變成object類型,而咱們知道裝箱操做是須要耗費一點時間的,那麼咱們能夠經過預見裝箱操做來對其作必定的優化工做。以下面這個極端的例子所示:
// 編譯器不須要每次調用Debug.Log函數的時候都執行裝箱操做 void PrintingManyTimes(int n) { object obj = n; for (int i = 0; i < 500; i++) Debug.Log(obj); }