裝箱(boxing)和拆箱(unboxing)是C#類型系統的核心概念。html
值類型繼承至System.ValueType,引用類型繼承至System.Object,詳細的類繼承關係以下圖所示:dom
1 int n = 100; 2 //有沒有發生裝箱?沒有,只是調用方法.查看IL沒有box,unbox關鍵字 3 string s = Convert.ToString(n); 4 int m = int.Parse(s); 5 Console.ReadKey();
裝拆箱:3d
1 int n = 100; 2 object o = n;//發生了一次裝箱 3 int m = (int)o; //發生了一次拆箱 4 Console.WriteLine(m); 5 Console.ReadKey();
查看IL代碼以下:指針
注意問題:裝箱的時候是什麼類型,拆箱的時候也必須使用對應的類型拆箱。不然會報錯code
=============================================================================================
以前寫了一篇比較是否爲同一對象(比較是否爲同一對象),object.ReferenceEquals若是兩個參數都是值類型會是怎樣的呢?
1 int n = 100; 2 int m = 100; 3 Console.WriteLine(n.Equals(m)); 4 Console.WriteLine(object.ReferenceEquals(n, m)); 5 Console.ReadKey();
運行結果是false,咱們來查看下IL代碼,很明顯,n和m都裝箱變爲了引用類型,它們所指向的地址不同,不管如何都是不成立的
=================================================================================
拼接字符串也會涉及裝箱問題:好比:
1 int n = 10; 2 object o = n; //裝箱一次 3 n = 100; 4 Console.WriteLine(n + "," + (int)o); //裝箱兩次,拆箱一次 5 Console.ReadKey();
仍是得查看一下IL代碼:由於拼接字符串是調用string.Concat(object,object,object)這個方法,每拼接一個字符串會把int隱式裝箱再鏈接
======================================================================
裝箱和拆箱性能問題
使用ArrayList:
1 ArrayList arrInt = new ArrayList(); 2 Stopwatch watch = new Stopwatch(); 3 watch.Start(); 4 for (int i = 0; i < 1000000; i++) 5 { 6 arrInt.Add(i); 7 } 8 watch.Stop(); 9 Console.WriteLine(watch.Elapsed); 10 Console.ReadKey();
運行結果:
使用泛型:
1 //使用泛型集合避免裝箱和拆箱。 2 List<int> arrInt = new List<int>(); 3 Stopwatch watch = new Stopwatch(); 4 watch.Start(); 5 for (int i = 0; i < 1000000; i++) 6 { 7 arrInt.Add(i); 8 } 9 watch.Stop(); 10 Console.WriteLine(watch.Elapsed); 11 Console.ReadKey();
運行結果:
這能夠看出裝拆箱仍是比較影響性能的