C# 裝箱和拆箱的知識(shí)回顧
裝箱是將值類(lèi)型轉(zhuǎn)換為 object 類(lèi)型或由此值類(lèi)型實(shí)現(xiàn)的任何接口類(lèi)型的一個(gè)過(guò)程。 當(dāng) CLR 對(duì)值類(lèi)型進(jìn)行裝箱時(shí),會(huì)將該值包裝到 System.Object 內(nèi)部,再將后者存儲(chǔ)在托管堆上。 拆箱將從對(duì)象中提取值類(lèi)型。 裝箱是隱式的;拆箱是顯式的。 裝箱和拆箱的概念是類(lèi)型系統(tǒng) C# 統(tǒng)一視圖的基礎(chǔ),其中任一類(lèi)型的值都被視為一個(gè)對(duì)象。
在下面的示例中,將整型變量 i 進(jìn)行了裝箱并分配給對(duì)象 obj。
static void Main(string[] args)
{
var i = 123; //System.Int32
//對(duì) i 裝箱(隱式)
object obj = i;
Console.Read();
}
然后,可以將對(duì)象 obj 拆箱并分配給整型變量 i。
static void Main(string[] args)
{
var i = 123; //System.Int32
//對(duì) i 裝箱(隱式)
object obj = i;
//對(duì) obj 進(jìn)行拆箱(顯式)
i = (int)obj;
Console.Read();
}
這里用代碼進(jìn)行演示裝箱拆箱操作:
static void Main(string[] args)
{
//使用 string.Format 演示裝箱的使用,在這里 24 會(huì)被進(jìn)行裝箱操作
var formatStr = string.Format("{0} {1}.", "I'm", 24);
Console.WriteLine($"formatStr: {formatStr}");
var objs = new List<object>();
for (int i = 0; i < 5; i++)
{
//每一次 i 都會(huì)裝箱到 objs 中
objs.Add(i);
}
Console.WriteLine("==========");
foreach (var obj in objs)
{
//兩個(gè) object 類(lèi)型不能直接使用 * ,需要使用 int 進(jìn)行顯式拆箱
Console.WriteLine($"{obj} * {obj} = {(int)obj * (int)obj}");
}
Console.Read();
}

性能
相對(duì)于簡(jiǎn)單的賦值而言,裝箱和取消裝箱過(guò)程需要進(jìn)行大量的計(jì)算。對(duì)值類(lèi)型進(jìn)行裝箱時(shí),必須分配并構(gòu)造一個(gè)新對(duì)象。拆箱所需的強(qiáng)制轉(zhuǎn)換也需要進(jìn)行大量的計(jì)算,只是程度較輕。如果你的操作正處于循環(huán)的中心,你會(huì)很明顯的感覺(jué)到性能問(wèn)題。
裝箱
裝箱用于在堆中存儲(chǔ)值類(lèi)型。 裝箱是值類(lèi)型到 object 類(lèi)型或到此值類(lèi)型所實(shí)現(xiàn)的任何接口類(lèi)型的隱式轉(zhuǎn)換。對(duì)值類(lèi)型裝箱會(huì)在堆中分配一個(gè)對(duì)象實(shí)例,并將該值復(fù)制到新的對(duì)象中。
請(qǐng)看以下值類(lèi)型變量的聲明:
var i = 123; //System.Int32
以下語(yǔ)句對(duì)變量 i 隱式應(yīng)用了裝箱操作:
//對(duì) i 裝箱(隱式)進(jìn)對(duì)象 obj object obj = i;
此語(yǔ)句的結(jié)果是在堆棧上創(chuàng)建對(duì)象引用 o,而在堆上則引用 int 類(lèi)型的值。 該值是賦給變量 i 的值類(lèi)型值的一個(gè)副本。 下圖說(shuō)明了兩個(gè)變量 i 和 o之間的差異。

當(dāng)然,你也可以選擇執(zhí)行顯式裝箱,但顯式裝箱從來(lái)不是必需的。
拆箱
拆箱是從 object 類(lèi)型到值類(lèi)型或從接口類(lèi)型到實(shí)現(xiàn)該接口的值類(lèi)型的顯式轉(zhuǎn)換。 拆箱的操作包括:
檢查對(duì)象實(shí)例,以確保它是給定值類(lèi)型的裝箱值。
將該值從實(shí)例復(fù)制到值類(lèi)型變量中。
int i = 123; // 值類(lèi)型 object o = i; // 裝箱 int j = (int)o; // 拆箱

要在運(yùn)行時(shí)成功拆箱值類(lèi)型,被拆箱的項(xiàng)必須是對(duì)一個(gè)對(duì)象的引用,該對(duì)象是先前通過(guò)裝箱該值類(lèi)型的實(shí)例創(chuàng)建的。 嘗試取消裝箱 null 會(huì)導(dǎo)致 NullReferenceException。 嘗試取消裝箱對(duì)不兼容值類(lèi)型的引用會(huì)導(dǎo)致 InvalidCastException。
以上就是本文的全部?jī)?nèi)容,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,同時(shí)也希望多多支持腳本之家!
相關(guān)文章
C#實(shí)現(xiàn)char字符數(shù)組與字符串相互轉(zhuǎn)換的方法
這篇文章主要介紹了C#實(shí)現(xiàn)char字符數(shù)組與字符串相互轉(zhuǎn)換的方法,結(jié)合實(shí)例形式簡(jiǎn)單分析了C#字符數(shù)組轉(zhuǎn)字符串及字符串轉(zhuǎn)字符數(shù)組的具體實(shí)現(xiàn)技巧,需要的朋友可以參考下2017-02-02
淺析C#中靜態(tài)方法和非靜態(tài)方法的區(qū)別
C#靜態(tài)方法與非靜態(tài)方法的區(qū)別不僅僅是概念上的,那么他們有什么具體的區(qū)別呢?讓我們通過(guò)本文向大家介紹下C#中靜態(tài)方法和非靜態(tài)方法的區(qū)別,一起看看吧2017-09-09
Unity UGUI LayoutRebuilder自動(dòng)重建布局介紹及使用
這篇文章主要為大家介紹了Unity UGUI LayoutRebuilder自動(dòng)重建布局介紹及使用,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07
C#環(huán)形隊(duì)列的實(shí)現(xiàn)方法詳解
這篇文章先是簡(jiǎn)單的給大家介紹了什么是環(huán)形隊(duì)列和環(huán)形隊(duì)列的優(yōu)點(diǎn),然后通過(guò)實(shí)例代碼給大家介紹C#如何實(shí)現(xiàn)環(huán)形隊(duì)列,有需要的朋友們可以參考借鑒,下面來(lái)一起看看吧。2016-09-09
C# SendMail發(fā)送郵件功能實(shí)現(xiàn)
這篇文章主要為大家詳細(xì)介紹了C# SendMail發(fā)送郵件功能實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-06
在web.config和app.config文件中增加自定義配置節(jié)點(diǎn)的方法
本篇文章主要是對(duì)在web.config和app.config文件中增加自定義配置節(jié)點(diǎn)的方法進(jìn)行了詳細(xì)的介紹,需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助2014-01-01
Unity中協(xié)程IEnumerator的使用方法介紹詳解
本文主要介紹了Unity中協(xié)程IEnumerator的使用方法介紹詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-06-06

