C#裝箱與拆箱操作的深入講解
疑問
都知道C#有裝箱和拆箱的操作,聽聞也都是講int類型轉(zhuǎn)換成object類型就是裝箱,將object類型再轉(zhuǎn)回int類型就是拆箱。
描述的通俗點:
- 裝箱 將值類型轉(zhuǎn)換成引用類型,
- 拆箱 將引用類型轉(zhuǎn)換成值類型。
- 那看來是要先了解一下引用類型和值類型了。
引用類型和值類型
在C#中,所有稱之為"類(class)"的類型,都是引用類型,而值類型都是標注為結(jié)構(struct)或者枚舉(enum)。
下面就來看一看引用類型和值類型,在實例化的時候發(fā)生了什么操作(首先自然是申明一下兩種類型了):
實例化了一個引用類型(SomeRef)和一個值類型(SomeVal),在調(diào)用的時候看看會發(fā)生什么:
上述代碼執(zhí)行完,可以看到在C#在操作引用類型的時候會執(zhí)行以下幾步
1.在托管堆上分配一塊內(nèi)存;
2.在分配的對象中,還需要加一些額外成員(類型對象指針,同步索引塊),這些成員必須初始化
3.對象中的字段要初始化為0,(本例中在執(zhí)行someRef.x = 5時,將字段x改為5)
4.在托管堆上分配一個對象時,可能會執(zhí)行一次垃圾收集操作
看完引用類型,接下來看一下值類型:
可以看到相對于引用類型,值類型直觀的地方感覺就輕便了許多,
1.在線程棧上分配一塊內(nèi)存
2.字段就在對象本身(沒有額外的成員,也不包含指向?qū)嵗闹羔槪?/p>
3.值類型實例不受垃圾回收期控制,減少了應用程序在生存周期內(nèi)進行垃圾回收的次數(shù)
上面對值類型和引用類型做了個初步的解釋
下面來看看什么情況下會進行裝箱和拆箱
裝箱
現(xiàn)在假設我們需要將一組坐標點存到ArrayList集合中,以便后續(xù)的步驟使用,那么我們會像下面這樣:
1.定義一個表示坐標的值類型,里面分別有字段x(橫坐標),字段y(縱坐標)
2.將幾個點存入ArrayList集合中
通過上例可以看到,通過調(diào)用ArrayList的Add方法,將Point坐標點添加到集合中
這是ArrayList的Add方法原型,可以看到他的接受參數(shù)是一個object類型
但是object類型是由"類(class)"來聲明的,前面說到聲明為"類(class)"的類型都是引用類型,但是我們的Point聲明為"結(jié)構(struct)"是一個值類型
可以看出,傳入的值類型會轉(zhuǎn)變?yōu)橐妙愋汀?/p>
C#中為了讓一個值類型轉(zhuǎn)換成一個引用類型,需要進行一次裝箱操作,下面看一下裝箱操作具體會發(fā)生哪些事情:
1.在托管堆上分配內(nèi)存
2.值類型的所有字段復制到新分配托管堆內(nèi)存上
3.返回對象的地址(這個地址是對一個對象的引用,值類型現(xiàn)在是一個引用類型)
注:舊的point對象不變,值類型轉(zhuǎn)換成引用類型的本質(zhì)是重新建立了一個已裝箱的Point對象(引用類型)
拆箱
談完裝箱,再來談一談拆箱
在上述的坐標點集合對象中,想要獲取第一個點的信息
現(xiàn)在知道ArrayList存的都是對象的引用(或指針),那要做的就是獲取元素0中包含的引用(或指針),并將它放到Point對象的實例pFirst中
來看看拆箱的過程,完成了那些事情
1.獲取已裝箱Point對象中的字段地址
2.將這些字段的值從托管堆中復制聲明的Point對象實例pFirst中(pFirst是值類型,在線程棧中分配內(nèi)存)
再說一句
目前在C#中,肯定不會再繼續(xù)用ArrayList來存儲一些對象的集合了,因為有了一組新的泛型集合,
例如用List<T>
在使用的就是就規(guī)定是什么類型,在存取數(shù)據(jù)的時候,不需要再進行多余的裝箱和拆箱操作
但是在寫代碼的時候還是會隱藏很多拆箱和裝箱的過程,注意盡量避免裝箱和拆箱的操作,如果不可避免,那就盡量減少裝箱和拆箱的操作,可以查看下方簡單示例(無實際意義):
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對我們的支持。
您可能感興趣的文章
- 01-10C#通過重寫Panel改變邊框顏色與寬度的方法
- 01-10C#實現(xiàn)實體類與字符串互相轉(zhuǎn)換的方法
- 01-10C#實現(xiàn)子窗體與父窗體通信方法實例總結(jié)
- 01-10時間戳與時間相互轉(zhuǎn)換(php .net精確到毫秒)
- 01-10基于C#實現(xiàn)簡單離線注冊碼生成與驗證
- 01-10C#裝箱和拆箱原理詳解
- 01-10C#開發(fā)中的垃圾回收機制簡析
- 01-10C#編程實現(xiàn)對象與JSON串互相轉(zhuǎn)換實例分析
- 01-10C#多線程編程之使用ReaderWriterLock類實現(xiàn)多用戶讀與單用戶寫同步
- 01-10輕松學習C#的裝箱與拆箱


閱讀排行
本欄相關
- 01-10C#通過反射獲取當前工程中所有窗體并
- 01-10關于ASP網(wǎng)頁無法打開的解決方案
- 01-10WinForm限制窗體不能移到屏幕外的方法
- 01-10WinForm繪制圓角的方法
- 01-10C#實現(xiàn)txt定位指定行完整實例
- 01-10WinForm實現(xiàn)仿視頻 器左下角滾動新
- 01-10C#停止線程的方法
- 01-10C#實現(xiàn)清空回收站的方法
- 01-10C#通過重寫Panel改變邊框顏色與寬度的
- 01-10C#實現(xiàn)讀取注冊表監(jiān)控當前操作系統(tǒng)已
隨機閱讀
- 08-05DEDE織夢data目錄下的sessions文件夾有什
- 04-02jquery與jsp,用jquery
- 01-10delphi制作wav文件的方法
- 01-10SublimeText編譯C開發(fā)環(huán)境設置
- 08-05dedecms(織夢)副欄目數(shù)量限制代碼修改
- 01-10使用C語言求解撲克牌的順子及n個骰子
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 01-11ajax實現(xiàn)頁面的局部加載
- 01-10C#中split用法實例總結(jié)
- 08-05織夢dedecms什么時候用欄目交叉功能?