日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

装箱(Boxing)和拆箱(Unboxing)

發(fā)布時間:2025/3/15 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 装箱(Boxing)和拆箱(Unboxing) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

首先介紹裝箱(Boxing)和拆箱(Unboxing)這兩個名詞。.Net的類型分為兩種,一種是值類型,另一種是引用類型。這兩個類型的本質(zhì)區(qū)別,值類型數(shù)據(jù)是分配在棧中,而引用類型數(shù)據(jù)分配在堆上。那么如果要把一個值類型數(shù)據(jù)放到堆上,就需要裝箱操作;反之,把一個放在堆上的值類型數(shù)據(jù)取出來,則需要進行拆箱操作。

例如,對于如下簡單的裝箱和拆箱操作語句。

??? int i = 123;

??? object obj = i;//Boxing

?

??? if( obj is int )

??????? int ?j = (int) obj;//Unboxing

?

為了,更好的詮釋裝箱和拆箱操作,我借用MSDN關(guān)于“Boxing”的解釋圖,具體如下。

? ??

明白了這兩名詞的意思,現(xiàn)在說說為什么要減少裝箱和拆箱操作。

原因有兩個,主要是關(guān)于效率:一個就是對于堆的操作效率比較低;另一個就是對于堆上分配的內(nèi)存資源,需要GC來回收,從而降低程序效率。

?

考慮到這兩點因素,那么需要在程序中減少裝箱和拆箱操作。

如何減少呢,涉及到這兩個操作比較多的是,格式化輸出操作,例如:String.Format,Console.WriteLine之類的語句。

例如:

??? Console.WriteLine( "Number list:{0}, {1}, {2}",

??????? 1,2,3 );

?

對于“1,2,3”來說,相當(dāng)于前面的“123”一樣,需要經(jīng)過裝箱和拆箱兩個操作。那么如何避免呢,其實只要向WriteLine傳遞引用類型數(shù)據(jù)即可,也就是按照如下的方式。

??? Console.WriteLine( "Number list:{0}, {1}, {2}",

??????? 1.ToString(),2.ToString(),3.ToString() );

?

由于“1.ToString()”的結(jié)果是String類型,屬于引用類型,因此不牽扯裝箱和拆箱操作。

?

其次,牽扯到裝箱和拆箱操作比較多的就是在集合中,例如:ArrayList或者HashTable之類。

把值類型數(shù)據(jù)放到集合中,可能會出現(xiàn)潛在錯誤。例如:

??? public struct Person

??? {

??????? private string _Name;

??????? public string Name

??????? {

??????????? get{ return _Name; }

??????????? set{ _Name = value; }

??????? }

?

??????? public Person( string PersonName )

??????? {

??????????? _Name = PersonName;

??????? }

?

??????? public override string ToString()

??????? {

??????????? return _Name;

??????? }

?

??? }

?

??? ArrayList arrPersons = new ArrayList();

??? Person p = new Person( "OldName" );

??? arrPersons.Add( p );

?? ?

?? ?

??? p = ( Person ) arrPersons[0] ;

??? p.Name = "NewName";

?

??? Debug.WriteLine( ( (Person ) arrPersons[0] ).Name );//It's "OldName"

?

這個問題其實在前面的文章中已經(jīng)講過了。有人可能會說,是否可以按照如下的方式去修改呢。

( (Person ) arrPersons[0] ).Name = "NewName";//Can't be compiled

?

很不幸,如上操作不能通過編譯。為什么呢,對于“( (Person ) arrPersons[0] )”來說,是系統(tǒng)用一個臨時變量來接收拆箱后的值類型數(shù)據(jù),那么由于值類型是分配在棧上,那么操作是對實體操作,可是系統(tǒng)不允許對一個臨時值類型數(shù)據(jù)進行修改操作。

?? ?

??? ArrayList arrPersons = new ArrayList();

??? Person p = new Person( "OldName" );

??? arrPersons.Add( p );

?? ?

??? // Try to change the name

??? p = ( Person ) arrPersons[0] ;

??? p.Name = "NewName";

?

??? arrPersons.RemoveAt( 0 );//Remove old data first

??? arrPersons.Insert( 0, p );//Add new data

??? Debug.WriteLine( ( (Person ) arrPersons[0] ).Name );//It's "NewName"

?

其實,這樣操作會產(chǎn)生過多裝箱和拆箱操作。那么更好的方法,可以通過接口來完成,從而減少裝箱和拆箱操作。對于這個例子的接口實現(xiàn)應(yīng)該如下。

??? public interface IPersonName

??? {

??????? string Name{ get;set;}

??? }

?

??? public struct Person:IPersonName

??? {

??????? private string _Name;

??????? public string Name

??????? {

??????????? get{ return _Name; }

??????????? set{ _Name = value; }

??????? }

?

??????? public Person( string PersonName )

??????? {

??????????? _Name = PersonName;

??????? }

?

??????? public override string ToString()

??????? {

??????????? return _Name;

??????? }

??? }

?

????? ?

??? ArrayList arrPersons = new ArrayList();

??? Person p = new Person( "OldName" );

??? arrPersons.Add( p );

??

??? // Change the name

??? ( (IPersonName)arrPersons[0] ).Name = "NewName";

?

??? Debug.WriteLine( ( (Person ) arrPersons[0] ).Name );//It's "NewName"

?

很多人就問,為什么值類型不能修改,即

( (Person ) arrPersons[0] ).Name = "NewName";//Can't be compiled

而如上的接口類型就能修改呢,即

( (IPersonName)arrPersons[0] ).Name = "NewName";

這是由于產(chǎn)生的臨時變量的類型不同,前者已經(jīng)在前面進行說明了,后者由于產(chǎn)生的臨時變量的類型為IPersonName,屬于引用類型,那么相當(dāng)于臨時變量就是原對象的引用,那么對于它的修改會直接修改到原對象,因此是可以的。可以說這里的不同本身在于產(chǎn)生臨時對象的類型不同,從而造成本質(zhì)的區(qū)別。

通過接口來改寫,這樣就減少了裝箱和拆箱操作,同時也保證了修改的正確性。不過要注意的是,這里接口是引用類型,如果接口訪問的或者返回的是值類型,那么用接口雖說能實現(xiàn)了,但是對于裝箱和拆箱操作來說,并沒有減少。

對于裝箱和拆箱操作來說,基本上就講完了,只要記住頻繁裝箱和拆箱操作會降低程序效率,因此在編寫的時候要盡量避免。


本文來自CSDN博客,轉(zhuǎn)載請標(biāo)明出處:http://blog.csdn.net/songxiaozhao/archive/2008/04/01/2235012.aspx?

轉(zhuǎn)載于:https://www.cnblogs.com/purplefox2008/archive/2010/08/26/1808892.html

總結(jié)

以上是生活随笔為你收集整理的装箱(Boxing)和拆箱(Unboxing)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。