小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

【C#】 裝箱 (boxing) 和拆箱 (unboxing)

 ThinkTank_引擎 2018-09-11

目錄:

1. 裝箱和拆箱

2. 深入理解裝箱和拆箱

3. int[] to object[],值類型數(shù)組到對象數(shù)組的轉(zhuǎn)化

4. 使用泛型減少裝箱和拆箱

1.  裝箱和拆箱

裝箱 就是把“值類型”轉(zhuǎn)換成“引用類型”;

拆箱 就是把“引用類型”轉(zhuǎn)換成“值類型”;

        首先,我們要弄明白為什么需要裝箱和拆箱。C#的所有類型,包括int、boo等,都繼承自System.Object,但是卻又有值類型和引用類型之分。這時(shí)你要問,int是繼承自object類型的,object是引用類型,那為何int不是引用類型而是值類型的呢?這就涉及到裝箱和拆箱的概念了。

         我們知道對象是創(chuàng)建在堆上的,它的創(chuàng)建和銷毀必然帶來額外的CPU和內(nèi)存消耗。如果將int,boo等微小而常用的數(shù)據(jù)類型都放在堆上創(chuàng)建和銷毀,語言的性能將會(huì)被極大的限制,有時(shí)甚至是無法忍受的。C#將值類型和引用類型分開,值類型直接在棧中被創(chuàng)建,超過作用域后直接銷毀。當(dāng)需要值類型成為對象時(shí),使用裝箱操作,讓值類型變?yōu)橐粋€(gè)引用類型的對象。這樣,我們就可以使用object作為通用的接口統(tǒng)一語言內(nèi)的一切類型。

        拆箱 在MSDN官方文檔里用的是 取消裝箱。事實(shí)上拆箱是裝箱的逆操作,也就是說我們只對裝過箱的引用類型(通常是object對象)進(jìn)行拆箱操作。單純拆箱操作的后果無法設(shè)想的。

        裝箱和拆箱是C#的核心概念,C#利用其完成類型系統(tǒng)的統(tǒng)一。有了裝箱,任何類型的值都可以視為一個(gè)對象。CLR在裝箱時(shí)是將值類型包裝到System.Object的內(nèi)部,再將其存儲(chǔ)到托管堆上。拆箱是從對象中提取值類型。裝箱是隱式的而拆箱是顯示的。

1
2
3
4
5
6
7
8
//裝箱 boxing
int i = 3 ;  //分配在棧上
object o = i ;//隱式裝箱操作,int i 在堆上
object b = (object)i ; //顯示裝箱操作
//拆箱 unboxing
int j = (int) o ;//顯示拆箱(將對象o拆箱為int類型)
int k = b ;//error!!, 不能隱式拆箱

拆箱 的操作包括

1,檢查對象實(shí)例,以卻確保它是給定值類型的裝箱值。

2,將該值從實(shí)例復(fù)制到值類型變量中。

 

下面來看看這個(gè)例子:

1
2
3
int i=0;
System.Object obj=i;
Console.WriteLine(i+","+(int)obj);

其中共發(fā)生了3次裝箱和一次拆箱!^_^,看出來了吧?!
第一次是將i裝箱,第2次是輸出的時(shí)候?qū)轉(zhuǎn)換成string類型,而string類型為引用類型,即又是裝箱,第三次裝箱就是(int)obj的轉(zhuǎn)換成string類型,裝箱!
拆箱就是(int)obj,將obj拆箱??!

2.  深入理解裝箱和拆箱

1
object o = 1 ;

這句話的IL代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
.locals init (
  [0] object objValue
  ) //以上三行IL表示聲明object類型的名稱為objValue的局部變量
  IL_0000: nop
  IL_0001: ldc.i4.s 1 //表示將整型數(shù)1放到棧頂
  IL_0003: box [mscorlib]System.Int32 //執(zhí)行IL box指令,在內(nèi)存堆中申請System.Int32類型需要的堆空間
  IL_0008: stloc.0 //彈出堆棧上的變量,將它存儲(chǔ)到索引為0的局部變量中

 

注意注釋的部分。執(zhí)行裝箱操作時(shí)不可避免的要在堆上申請內(nèi)存空間,并將堆棧上的值類型數(shù)據(jù)復(fù)制到申請的堆內(nèi)存空間上,這肯定是要消耗內(nèi)存和cpu資源的。

1
2
3
object objValue = 4;
int value = (int)objValue;

同樣,看看IL代碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
.locals init (
  [0] object objValue,
  [1] int32 'value'
  ) //上面IL聲明兩個(gè)局部變量object類型的objValue和int32類型的value變量
  IL_0000: nop
  IL_0001: ldc.i4.4 //將整型數(shù)字4壓入棧
  IL_0002: box [mscorlib]System.Int32 //執(zhí)行IL box指令,在內(nèi)存堆中申請System.Int32類型需要的堆空間
  IL_0007: stloc.0 //彈出堆棧上的變量,將它存儲(chǔ)到索引為0的局部變量中
  IL_0008: ldloc.0//將索引為0的局部變量(即objValue變量)壓入棧
  IL_0009: unbox.any [mscorlib]System.Int32 //執(zhí)行IL 拆箱指令unbox.any 將引用類型object轉(zhuǎn)換成System.Int32類型
  IL_000e: stloc.1 //將棧上的數(shù)據(jù)存儲(chǔ)到索引為1的局部變量即value

 

拆箱操作的執(zhí)行過程和裝箱操作過程正好相反,是將存儲(chǔ)在堆上的引用類型值轉(zhuǎn)換為值類型并給值類型變量。裝箱操作和拆箱操作是要額外耗費(fèi)cpu和內(nèi)存資源的,所以在c# 2.0之后引入了泛型來減少裝箱操作和拆箱操作消耗。

3. int[] to object[],值類型數(shù)組到對象數(shù)組的轉(zhuǎn)化

我們不能直接把值類型的數(shù)組賦值給對象數(shù)組,例如:

1
2
int[] array  = new int[] { 0 } ;
object[] oiArray = (object[])array;//error!! 不能將int[] 轉(zhuǎn)換到 object[]
1
string[] a={"1","2","3"};
1
object[] osArray = a ;//正確,a是引用類型數(shù)組,不存在裝箱和拆箱

(object[])a無法將a所有的值類型對象“直接”轉(zhuǎn)換為引用類型,所以編譯器不會(huì)通過這個(gè)轉(zhuǎn)換??梢允褂萌缦碌姆绞竭_(dá)到目的:

1
2
3
4
5
6
int[] array  = new int[] { 0 } ;
object[] oArray = new object[array.Length];
for(int i =0 ; i< array.Length ; i++)
{
   oArray[i] = array[i]; //隱式裝箱
}

 

4. 使用泛型減少裝箱和拆箱

        有時(shí)說使用泛型能提高C#程序的性能,有一部分性能的提升是由減少了裝箱和拆箱帶來的??疾煜旅娴拇a:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Test
{
    object _o  ;
     
    public Test(object o)
    {
    _o = o ;
    }
}
public class Test<T>
{
    T _o ;
    public Test(T o)
    {
        _o = o ;
    }
}

        第一個(gè)Test類中沒有使用泛型,如果將一個(gè)int類型的值傳入Test,將會(huì)引發(fā)多次的裝箱和拆箱操作。而泛型類在實(shí)例化時(shí)已經(jīng)明確了類型,復(fù)制操作時(shí)就不會(huì)有裝箱和拆箱操作了。

 

引用:

1. 玉開 http://www.cnblogs.com/yukaizhao/archive/2011/10/18/csharp_box_unbox_1.html

2. MSDN https://msdn.microsoft.com/zh-cn/library/yz2be5wk.aspx

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請遵守用戶 評(píng)論公約

    類似文章 更多