輕松學(xué)習(xí)C#的裝箱與拆箱
首先看一看什么是裝箱和拆箱?
簡(jiǎn)單的來(lái)說(shuō):
裝箱就是值類型轉(zhuǎn)換為引用類型;
拆箱就是引用類型轉(zhuǎn)換為值類型。
值類型,包括原類型(Sbyte、Byte、Short、Ushort、Int、Uint、Long、Ulong、Char、Float、Double、Bool、Decimal)、枚舉 (enum) 、結(jié)構(gòu) (struct)。
引用類型包括類、數(shù)組、接口、委托、字符串等。
裝箱:值類型到引用類型或到此值類型所實(shí)現(xiàn)的任何接口類型的隱式轉(zhuǎn)換
例如: int temp = 3;
System.Object obj = temp;
其中,temp為值類型,在棧中分配;當(dāng)分配obj這個(gè)引用類型時(shí),我們需要在堆中分配一個(gè)obj對(duì)象,然后把temp值賦給它,這么一系列的過(guò)程就是裝箱的過(guò)程。
拆箱:從引用類型到任意值類型的顯式轉(zhuǎn)換。與裝箱不同,拆箱式顯示轉(zhuǎn)換。
例如:int temp = 3;
System.Object obj = temp;
int i = (int) obj;
拆箱過(guò)程中,首先來(lái)確定對(duì)象obj為一個(gè)值類型的裝箱值,然后把值賦給值類型。
隱式轉(zhuǎn)換總會(huì)成功的情況,不會(huì)拋出異常:
(1)、從派生類到基類;
(2)、從派生接口到基接口;
(3)、從類到接口(該類實(shí)現(xiàn)了接口);
(4)、從Null到任何類;
顯式引用轉(zhuǎn)換,以下可能拋出異常,轉(zhuǎn)換不一定成功:
(1)、從基類到派生類;
(2)、從接口到接口(基接口到派生接口或者倆接口沒(méi)有關(guān)系);
(3)、從接口到類(該類實(shí)現(xiàn)了該接口或該類未封閉);
(4)、從類到接口(該類未實(shí)現(xiàn)該接口且該類未封閉);
上面簡(jiǎn)單的介紹了拆箱和裝箱的定義,下面就來(lái)討論一下裝箱和拆箱與堆和棧怎樣使用
其中值類型是在棧中分配內(nèi)存,本身的聲明就是一個(gè)初始化的過(guò)程,其不需要進(jìn)行垃圾回收,只要超出所定義的作用范圍會(huì)自動(dòng)釋放內(nèi)存,而引用類型則是在堆中分配的,和java一樣,在堆種分配內(nèi)存,而其托管堆進(jìn)行垃圾回收。當(dāng)兩種數(shù)據(jù)類型進(jìn)行轉(zhuǎn)換時(shí)就引出了裝箱/拆箱。
比較裝箱和拆箱的優(yōu)缺點(diǎn)
裝箱和拆箱雖然滿足了兩只類型之間的轉(zhuǎn)換。但是從裝箱的過(guò)程中不難看出,每次裝箱時(shí)要在堆中new一個(gè)新的對(duì)象,當(dāng)量特別大是肯定會(huì)大大影響程序的效率。事物總有兩面性,every sword has two sides,事情便簡(jiǎn)單了,性能也下來(lái)了。所以,在應(yīng)用中,我們應(yīng)該盡量避免裝箱操作。
了解了裝箱和拆箱的操作,我們可以清楚的明白:裝箱操作會(huì)導(dǎo)致數(shù)據(jù)在堆和棧上進(jìn)行拷貝,頻繁的裝箱操作會(huì)性能損失。而相比而言拆箱過(guò)程對(duì)性能損耗還是比較小的。
裝箱和拆箱的詳細(xì)步驟
1、裝箱(box)的詳細(xì)步驟:
(1)、在堆上分配一個(gè)內(nèi)存空間,大小等于需要裝箱的值類型對(duì)象的大小加上兩個(gè)引用類型對(duì)象都擁有的成員:類型對(duì)象指針和同步塊引用。
(2)、把堆棧上的值類型對(duì)象復(fù)制到堆上新分配的對(duì)象。
(3)、返回一個(gè)指向堆上新對(duì)象的引用,并且存儲(chǔ)到堆棧上被裝箱的那個(gè)值類型的對(duì)象里。
這個(gè)步驟不需要程序員自己編寫,在任何出現(xiàn)裝箱的地方,編譯器會(huì)自動(dòng)加上執(zhí)行以上功能的IL代碼。
所謂的拆箱就是裝箱對(duì)應(yīng)著的概念,但拆箱的過(guò)程和裝箱并不是倒過(guò)來(lái)就是:
2、拆箱(unbox.any)的詳細(xì)步驟
如果為待拆箱對(duì)象為null,拋出NullReferenceException異常。
如果引用指向的不是一個(gè)期望對(duì)象的已裝箱對(duì)象,拋出InvalidCastException異常。
(1)、獲取已裝箱對(duì)象中各個(gè)字段的地址,這個(gè)過(guò)程就是“拆箱”
需要說(shuō)明的是一般拆箱以后會(huì)伴隨著對(duì)象的拷貝,但拷貝操作已經(jīng)不是拆箱的范疇。
下面舉兩個(gè)小的例子來(lái)實(shí)現(xiàn)什么是裝箱、拆箱以及怎樣避免因頻繁的裝箱而耗費(fèi)內(nèi)存
(1)、裝箱:
using System; public class Test { public static void Main(String[] args) { int i = 10; //將值類型的i裝箱 //需要注意的是:這里的裝箱采用的是值的拷貝 object obj = i; //檢驗(yàn)是否裝箱成功了 if(obj is int) { Console.WriteLine("數(shù)據(jù)已經(jīng)裝箱!"); } //我們?cè)谶@里更改i的值 i = 33; Console.WriteLine("int i現(xiàn)在的值是:{0}",i); Console.WriteLine("int i裝箱的值是:{0}",obj); } }
(2)、拆箱:
int i = 10; object obj = i; int j = (int)obj; (3)、避免頻繁的裝箱: int i = 10; int j = 20; int s = 30; Console.WriteLine("i的值為{0},j的值為{1},s的值為{2}", i.ToString(), j.ToString(), s.ToString());
以上就是介紹了C#的裝箱與拆箱,思路很清晰,涉及的內(nèi)容很全面,包括裝箱和拆箱的優(yōu)缺點(diǎn)、裝箱和拆箱的步驟等,很適合初學(xué)者進(jìn)行學(xué)習(xí)。
上一篇:C#編程實(shí)現(xiàn)四舍五入、向上及下取整的方法
欄 目:C#教程
下一篇:C#實(shí)現(xiàn)DataList里面嵌套DataList的折疊菜單
本文標(biāo)題:輕松學(xué)習(xí)C#的裝箱與拆箱
本文地址:http://mengdiqiu.com.cn/a1/C_jiaocheng/6844.html
您可能感興趣的文章
- 01-10C#通過(guò)反射獲取當(dāng)前工程中所有窗體并打開(kāi)的方法
- 01-10關(guān)于ASP網(wǎng)頁(yè)無(wú)法打開(kāi)的解決方案
- 01-10WinForm限制窗體不能移到屏幕外的方法
- 01-10WinForm繪制圓角的方法
- 01-10C#停止線程的方法
- 01-10WinForm實(shí)現(xiàn)仿視頻 器左下角滾動(dòng)新聞效果的方法
- 01-10C#通過(guò)重寫Panel改變邊框顏色與寬度的方法
- 01-10C#實(shí)現(xiàn)清空回收站的方法
- 01-10C#實(shí)現(xiàn)讀取注冊(cè)表監(jiān)控當(dāng)前操作系統(tǒng)已安裝軟件變化的方法
- 01-10C#實(shí)現(xiàn)多線程下載文件的方法


閱讀排行
- 1C語(yǔ)言 while語(yǔ)句的用法詳解
- 2java 實(shí)現(xiàn)簡(jiǎn)單圣誕樹(shù)的示例代碼(圣誕
- 3利用C語(yǔ)言實(shí)現(xiàn)“百馬百擔(dān)”問(wèn)題方法
- 4C語(yǔ)言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)
- 5c語(yǔ)言計(jì)算三角形面積代碼
- 6什么是 WSH(腳本宿主)的詳細(xì)解釋
- 7C++ 中隨機(jī)函數(shù)random函數(shù)的使用方法
- 8正則表達(dá)式匹配各種特殊字符
- 9C語(yǔ)言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
- 10C語(yǔ)言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
本欄相關(guān)
- 01-10C#通過(guò)反射獲取當(dāng)前工程中所有窗體并
- 01-10關(guān)于ASP網(wǎng)頁(yè)無(wú)法打開(kāi)的解決方案
- 01-10WinForm限制窗體不能移到屏幕外的方法
- 01-10WinForm繪制圓角的方法
- 01-10C#實(shí)現(xiàn)txt定位指定行完整實(shí)例
- 01-10WinForm實(shí)現(xiàn)仿視頻 器左下角滾動(dòng)新
- 01-10C#停止線程的方法
- 01-10C#實(shí)現(xiàn)清空回收站的方法
- 01-10C#通過(guò)重寫Panel改變邊框顏色與寬度的
- 01-10C#實(shí)現(xiàn)讀取注冊(cè)表監(jiān)控當(dāng)前操作系統(tǒng)已
隨機(jī)閱讀
- 01-10delphi制作wav文件的方法
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改
- 01-10使用C語(yǔ)言求解撲克牌的順子及n個(gè)骰子
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什
- 04-02jquery與jsp,用jquery
- 01-11ajax實(shí)現(xiàn)頁(yè)面的局部加載
- 01-10C#中split用法實(shí)例總結(jié)
- 01-11Mac OSX 打開(kāi)原生自帶讀寫NTFS功能(圖文
- 01-10SublimeText編譯C開(kāi)發(fā)環(huán)境設(shè)置