【C# 裝箱(Boxing)與取消裝箱(Unboxing)】

文章來自微軟官網: 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之間的差別。對象

BoxingConversion 圖

還能夠像下面的示例同樣執行顯式裝箱,但顯式裝箱歷來不是必須的: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);
}    
相關文章
相關標籤/搜索