裝箱和拆箱 目錄 性能 裝箱 拆箱 介紹 裝箱是將值類型轉換為 object 類型或由此值類型實現的任何介面類型的一個過程。 當 CLR 對值類型進行裝箱時,會將該值包裝到 System.Object 內部,再將後者存儲在托管堆上。 拆箱將從對象中提取值類型。 裝箱是隱式的;拆箱是顯式的。 裝箱和拆 ...
裝箱和拆箱
目錄
- 性能
- 裝箱
- 拆箱
介紹
裝箱是將值類型轉換為 object
類型或由此值類型實現的任何介面類型的一個過程。 當 CLR 對值類型進行裝箱時,會將該值包裝到 System.Object 內部,再將後者存儲在托管堆上。 拆箱將從對象中提取值類型。 裝箱是隱式的;拆箱是顯式的。 裝箱和拆箱的概念是類型系統 C# 統一視圖的基礎,其中任一類型的值都被視為一個對象。
在下麵的示例中,將整型變數 i
進行了裝箱並分配給對象 obj
。
1 static void Main(string[] args) 2 { 3 var i = 123; //System.Int32 4 5 //對 i 裝箱(隱式) 6 object obj = i; 7 8 Console.Read(); 9 }
然後,可以將對象 obj 拆箱並分配給整型變數 i。
1 static void Main(string[] args) 2 { 3 var i = 123; //System.Int32 4 5 //對 i 裝箱(隱式) 6 object obj = i; 7 8 //對 obj 進行拆箱(顯式) 9 i = (int)obj; 10 11 Console.Read(); 12 }
這裡用代碼進行演示裝箱拆箱操作:
1 static void Main(string[] args) 2 { 3 //使用 string.Format 演示裝箱的使用,在這裡 24 會被進行裝箱操作 4 var formatStr = string.Format("{0} {1}.", "I'm", 24); 5 Console.WriteLine($"formatStr: {formatStr}"); 6 7 var objs = new List<object>(); 8 for (int i = 0; i < 5; i++) 9 { 10 //每一次 i 都會裝箱到 objs 中 11 objs.Add(i); 12 } 13 14 Console.WriteLine("=========="); 15 16 foreach (var obj in objs) 17 { 18 //兩個 object 類型不能直接使用 * ,需要使用 int 進行顯式拆箱 19 Console.WriteLine($"{obj} * {obj} = {(int)obj * (int)obj}"); 20 } 21 22 Console.Read(); 23 }
性能
相對於簡單的賦值而言,裝箱和取消裝箱過程需要進行大量的計算。對值類型進行裝箱時,必須分配並構造一個新對象。拆箱所需的強制轉換也需要進行大量的計算,只是程度較輕。如果你的操作正處於迴圈的中心,你會很明顯的感覺到性能問題。
裝箱
裝箱用於在堆中存儲值類型。 裝箱是值類型到 object
類型或到此值類型所實現的任何介面類型的隱式轉換。對值類型裝箱會在堆中分配一個對象實例,並將該值複製到新的對象中。
請看以下值類型變數的聲明:
var i = 123; //System.Int32
以下語句對變數 i
隱式應用了裝箱操作:
//對 i 裝箱(隱式)進對象 obj object obj = i;
此語句的結果是在堆棧上創建對象引用 o
,而在堆上則引用 int
類型的值。 該值是賦給變數 i
的值類型值的一個副本。 下圖說明瞭兩個變數 i
和 o
之間的差異。
當然,你也可以選擇執行顯式裝箱,但顯式裝箱從來不是必需的。
拆箱
拆箱是從 object
類型到值類型或從介面類型到實現該介面的值類型的顯式轉換。 拆箱的操作包括:
-
檢查對象實例,以確保它是給定值類型的裝箱值。
-
將該值從實例複製到值類型變數中。
1 int i = 123; // 值類型 2 object o = i; // 裝箱 3 int j = (int)o; // 拆箱
要在運行時成功拆箱值類型,被拆箱的項必須是對一個對象的引用,該對象是先前通過裝箱該值類型的實例創建的。 嘗試取消裝箱 null
會導致 NullReferenceException。 嘗試取消裝箱對不相容值類型的引用會導致 InvalidCastException。
C# 基礎回顧系列
《C# 知識回顧 - 表達式樹 Expression Trees》
《C# 知識回顧 - 特性 Attribute》、《剖析 AssemblyInfo.cs - 瞭解常用的特性 Attribute》《C# 知識回顧 - 委托 delegate》、《C# 知識回顧 - 委托 delegate (續)》
《C# 知識回顧 - 事件入門》、《C# 知識回顧 - Event 事件》
《string 與 String,大 S 與小 S 之間沒有什麼不可言說的秘密》
【博主】反骨仔
【出處】http://www.cnblogs.com/liqingwen/p/6189128.html
【參考】微軟官方文檔