C#之裝箱和拆箱

來源:互聯網
上載者:User

標籤:style   blog   http   color   使用   strong   

    在實際編碼過程中,有時候會出現裝箱和拆箱操作。下面就類分別認識一下:

需要注意的是,類型轉換和這個是不同的。Convert方法並沒有發生裝箱和拆箱操作,而是類型轉換,包括int.parse等等。

裝箱,是把實值型別拷貝了一個副本放在堆記憶體中。

拆箱,在參考型別直接找到實值型別儲存的位置(Person對象是參考型別,但其Age屬性是實值型別,也儲存在堆記憶體中),實際上我們往往拆箱後會用一個實值型別變數接收它。

例1:

1             int n = 10;2             Console.WriteLine(n);3             object o = n;//一次裝箱4             Console.WriteLine((int)o);5             Console.WriteLine(o);//這裡輸出的是字串"10",相當於Console.WriteLine(o.ToString());

    上面的代碼中,第2句話並沒有發生裝箱,因為Console.WriteLine()方法有一個int類型重載;第3句話發生一次裝箱;而第4句話(int)o發生一次拆箱,拆箱後的值被其values接收,如果沒有Console.WriteLine()方法有一個int類型重載的話,會馬上再次裝箱,因為這個重載,沒有發生裝箱;最後1句話,輸出的是字串"10",相當於Console.WriteLine(o.ToString())。所以在判斷一句話是否發生裝箱和拆箱要結合建構函式來看。

例2:

1             int n = 10;2 3             IComparable com = n;4 5             int m = (int)com;6 7             Console.WriteLine(m);

     上面的代碼中,第二句話發生了裝箱,第三句話發生了拆箱,因為int類型實現了IComparable介面。

例3:

1             int d = 999;2             object o = d; //裝箱3 4             //裝箱時使用什麼類型,拆箱時也必須使用同樣的類型。否則報異常5             double d1 = (double)o; //拆箱 
6 Console.WriteLine(d1);

例3中,編譯會報錯,以為在第2句話裝箱前是int類型,而拆箱時確是double。需要注意的是,裝箱前是什麼類型,拆箱後也必須是什麼類型,否則會報錯

例4:

 1            int n = 100; 2             M1(n); 3  4             string x = "a"; 5             double d1 = 10; 6             string y = "b"; 7             int n1 = 9; 8             string z = "c"; 9             string full = x + d1 + y + n1 + z;10             Console.WriteLine(full);11 12        //定義函數如下:13         static void M1(double d)14         {15             Console.WriteLine(d);16         }17 18         static void M1(object o)19         {20             Console.WriteLine(o);21         }

上面的代碼到底發生了幾次裝箱和拆箱呢?首先看M1()方法,經反編譯得知M1((double) n);由此可見,M1()方法並沒有去找object類型的重載,而是找了與之相近的double類型重載,所以沒有發生裝箱。第9句話經反編譯得知Console.WriteLine(string.Concat(new object[] { x, d1, y, n1, z }));它將double類型變數d1和int類型變數n1裝箱成object類型。所以上面的代碼只發生了2次裝箱。

裝箱和拆箱帶來的效能影響:

日常編碼中應避免裝箱和拆箱,因為他們會帶來效能的損耗。看下面的代碼:

 

1             ArrayList aList = new ArrayList();2             Stopwatch sw = new Stopwatch();3             sw.Start();4             for (int i = 0; i < 100000; i++)5             {6                 aList.Add(i);   //Add方法每添加一次發生一次裝箱7             }8             sw.Stop();9             Console.WriteLine("用時:"+sw.Elapsed);

 

運行結果:

我們換另一種:

1             List<int> aList = new List<int>();2             Stopwatch sw = new Stopwatch();3             sw.Start();4             for (int i = 0; i < 100000; i++)5             {6                 aList.Add(i);   7             }8             sw.Stop();9             Console.WriteLine("用時:" + sw.Elapsed);

運行結果:

由此可見,效能影響還是挺大的。

 

總結:

一)裝箱和拆箱的判斷依據:
1.發生在實值型別和參考型別之間;
2.具備父子類的關係。

二)判斷一句話是否發生裝箱和拆箱要結合建構函式來看;

三)裝箱前是什麼類型,拆箱後也必須是什麼類型,否則會報錯;

四)寫代碼的過程中應盡量避免裝箱和拆箱帶來的效能消耗。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.