C#裝箱與拆箱操作的深入講解
疑問
都知道C#有裝箱和拆箱的操作,聽聞也都是講int類型轉(zhuǎn)換成object類型就是裝箱,將object類型再轉(zhuǎn)回int類型就是拆箱。
描述的通俗點(diǎn):
- 裝箱 將值類型轉(zhuǎn)換成引用類型,
- 拆箱 將引用類型轉(zhuǎn)換成值類型。
- 那看來是要先了解一下引用類型和值類型了。
引用類型和值類型
在C#中,所有稱之為"類(class)"的類型,都是引用類型,而值類型都是標(biāo)注為結(jié)構(gòu)(struct)或者枚舉(enum)。
下面就來看一看引用類型和值類型,在實(shí)例化的時(shí)候發(fā)生了什么操作(首先自然是申明一下兩種類型了):
實(shí)例化了一個(gè)引用類型(SomeRef)和一個(gè)值類型(SomeVal),在調(diào)用的時(shí)候看看會(huì)發(fā)生什么:
上述代碼執(zhí)行完,可以看到在C#在操作引用類型的時(shí)候會(huì)執(zhí)行以下幾步
1.在托管堆上分配一塊內(nèi)存;
2.在分配的對(duì)象中,還需要加一些額外成員(類型對(duì)象指針,同步索引塊),這些成員必須初始化
3.對(duì)象中的字段要初始化為0,(本例中在執(zhí)行someRef.x = 5時(shí),將字段x改為5)
4.在托管堆上分配一個(gè)對(duì)象時(shí),可能會(huì)執(zhí)行一次垃圾收集操作
看完引用類型,接下來看一下值類型:
可以看到相對(duì)于引用類型,值類型直觀的地方感覺就輕便了許多,
1.在線程棧上分配一塊內(nèi)存
2.字段就在對(duì)象本身(沒有額外的成員,也不包含指向?qū)嵗闹羔槪?/p>
3.值類型實(shí)例不受垃圾回收期控制,減少了應(yīng)用程序在生存周期內(nèi)進(jìn)行垃圾回收的次數(shù)
上面對(duì)值類型和引用類型做了個(gè)初步的解釋
下面來看看什么情況下會(huì)進(jìn)行裝箱和拆箱
裝箱
現(xiàn)在假設(shè)我們需要將一組坐標(biāo)點(diǎn)存到ArrayList集合中,以便后續(xù)的步驟使用,那么我們會(huì)像下面這樣:
1.定義一個(gè)表示坐標(biāo)的值類型,里面分別有字段x(橫坐標(biāo)),字段y(縱坐標(biāo))
2.將幾個(gè)點(diǎn)存入ArrayList集合中
通過上例可以看到,通過調(diào)用ArrayList的Add方法,將Point坐標(biāo)點(diǎn)添加到集合中
這是ArrayList的Add方法原型,可以看到他的接受參數(shù)是一個(gè)object類型
但是object類型是由"類(class)"來聲明的,前面說到聲明為"類(class)"的類型都是引用類型,但是我們的Point聲明為"結(jié)構(gòu)(struct)"是一個(gè)值類型
可以看出,傳入的值類型會(huì)轉(zhuǎn)變?yōu)橐妙愋汀?/p>
C#中為了讓一個(gè)值類型轉(zhuǎn)換成一個(gè)引用類型,需要進(jìn)行一次裝箱操作,下面看一下裝箱操作具體會(huì)發(fā)生哪些事情:
1.在托管堆上分配內(nèi)存
2.值類型的所有字段復(fù)制到新分配托管堆內(nèi)存上
3.返回對(duì)象的地址(這個(gè)地址是對(duì)一個(gè)對(duì)象的引用,值類型現(xiàn)在是一個(gè)引用類型)
注:舊的point對(duì)象不變,值類型轉(zhuǎn)換成引用類型的本質(zhì)是重新建立了一個(gè)已裝箱的Point對(duì)象(引用類型)
拆箱
談完裝箱,再來談一談拆箱
在上述的坐標(biāo)點(diǎn)集合對(duì)象中,想要獲取第一個(gè)點(diǎn)的信息
現(xiàn)在知道ArrayList存的都是對(duì)象的引用(或指針),那要做的就是獲取元素0中包含的引用(或指針),并將它放到Point對(duì)象的實(shí)例pFirst中
來看看拆箱的過程,完成了那些事情
1.獲取已裝箱Point對(duì)象中的字段地址
2.將這些字段的值從托管堆中復(fù)制聲明的Point對(duì)象實(shí)例pFirst中(pFirst是值類型,在線程棧中分配內(nèi)存)
再說一句
目前在C#中,肯定不會(huì)再繼續(xù)用ArrayList來存儲(chǔ)一些對(duì)象的集合了,因?yàn)橛辛艘唤M新的泛型集合,
例如用List<T>
在使用的就是就規(guī)定是什么類型,在存取數(shù)據(jù)的時(shí)候,不需要再進(jìn)行多余的裝箱和拆箱操作
但是在寫代碼的時(shí)候還是會(huì)隱藏很多拆箱和裝箱的過程,注意盡量避免裝箱和拆箱的操作,如果不可避免,那就盡量減少裝箱和拆箱的操作,可以查看下方簡(jiǎn)單示例(無實(shí)際意義):
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
C#實(shí)現(xiàn)appSettings節(jié)點(diǎn)讀取與修改的方法
這篇文章主要介紹了C#實(shí)現(xiàn)appSettings節(jié)點(diǎn)讀取與修改的方法,是非常實(shí)用的技巧,需要的朋友可以參考下2014-10-10c#打印預(yù)覽控件中實(shí)現(xiàn)用鼠標(biāo)移動(dòng)頁面功能代碼分享
項(xiàng)目中需要實(shí)現(xiàn)以下功能:打印預(yù)覽控件中,可以用鼠標(biāo)拖動(dòng)頁面,以查看超出顯示范圍之外的部分內(nèi)容,下面就是實(shí)現(xiàn)代碼2013-12-12使用C#語言實(shí)現(xiàn)的查詢條件界面展開和收起功能
這篇文章主要介紹了使用C#語言實(shí)現(xiàn)的查詢條件界面展開和收起功能的完美解決方案,需要的朋友可以參考下2016-11-11使用C#實(shí)現(xiàn)一個(gè)簡(jiǎn)單的繪圖工具
這篇文章主要為大家詳細(xì)介紹了如何使用C#開發(fā)的簡(jiǎn)單繪圖工具,可以將簽名簡(jiǎn)單繪圖后的效果以圖片的形式導(dǎo)出,有需要的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-02-02C#實(shí)現(xiàn)文件上傳與下載功能實(shí)例
本篇文章主要介紹了C#實(shí)現(xiàn)文件上傳與下載,這里整理了詳細(xì)的代碼,有需要的小伙伴可以參考下。2016-12-12C#實(shí)現(xiàn)動(dòng)態(tài)顯示及動(dòng)態(tài)移除圖片方法
這篇文章主要介紹了C#實(shí)現(xiàn)動(dòng)態(tài)顯示及動(dòng)態(tài)移除圖片方法,對(duì)于C#的初學(xué)者了解圖像操作有一定的幫助,需要的朋友可以參考下2014-07-07