C 裝箱和拆箱

2022-03-22 11:38:57 字數 2346 閱讀 1106

都知道c#有裝箱和拆箱的操作,聽聞也都是講int型別轉換成object型別就是裝箱,將object型別再轉回int型別就是拆箱。

描述的通俗點:

裝箱將值型別轉換成引用型別,

拆箱將引用型別轉換成值型別。

那看來是要先了解一下引用型別和值型別了。

在c#中,所有稱之為"類(class)"的型別,都是引用型別,而值型別都是標註為結構(struct)或者列舉(enum)。

下面就來看一看引用型別和值型別,在例項化的時候發生了什麼操作(首先自然是申明一下兩種型別了):

例項化了乙個引用型別(someref)和乙個值型別(someval),在呼叫的時候看看會發生什麼:

上述**執行完,可以看到在c#在操作引用型別的時候會執行以下幾步

1.在託管堆上分配一塊記憶體;

2.在分配的物件中,還需要加一些額外成員(型別物件指標,同步索引塊),這些成員必須初始化

3.物件中的字段要初始化為0,(本例中在執行someref.x = 5時,將字段x改為5)  

4.在託管堆上分配乙個物件時,可能會執行一次垃圾收集操作

看完引用型別,接下來看一下值型別:

2.欄位就在物件本身(沒有額外的成員,也不包含指向例項的指標)

3.值型別例項不受垃圾**期控制,減少了應用程式在生存週期內進行垃圾**的次數

上面對值型別和引用型別做了個初步的解釋

下面來看看什麼情況下會進行裝箱和拆箱

現在假設我們需要將一組座標點存到arraylist集合中,以便後續的步驟使用,那麼我們會像下面這樣:

1.定義乙個表示座標的值型別,裡面分別有欄位x(橫座標),欄位y(縱座標)

2.將幾個點存入arraylist集合中

通過上例可以看到,通過呼叫arraylist的add方法,將point座標點新增到集合中

這是arraylist的add方法原型,可以看到他的接受引數是乙個object型別

但是object型別是由"類(class)"來宣告的,前面說到宣告為"類(class)"的型別都是引用型別,但是我們的point宣告為"結構(struct)"是乙個值型別

可以看出,傳入的值型別會轉變為引用型別。 

c#中為了讓乙個值型別轉換成乙個引用型別,需要進行一次裝箱操作,下面看一下裝箱操作具體會發生哪些事情:

1.在託管堆上分配記憶體

2.值型別的所有字段複製到新分配託管堆記憶體上

3.返回物件的位址(這個位址是對乙個物件的引用,值型別現在是乙個引用型別)

注:舊的point物件不變,值型別轉換成引用型別的本質是重新建立了乙個已裝箱的point物件(引用型別)

談完裝箱,再來談一談拆箱

在上述的座標點集合物件中,想要獲取第乙個點的資訊

現在知道arraylist存的都是物件的引用(或指標),那要做的就是獲取元素0中包含的引用(或指標),並將它放到point物件的例項pfirst中

來看看拆箱的過程,完成了那些事情

1.獲取已裝箱point物件中的字段位址

目前在c#中,肯定不會再繼續用arraylist來儲存一些物件的集合了,因為有了一組新的泛型集合,

例如用list

在使用的就是就規定是什麼型別,在訪問資料的時候,不需要再進行多餘的裝箱和拆箱操作

但是在寫**的時候還是會隱藏很多拆箱和裝箱的過程,注意盡量避免裝箱和拆箱的操作,如果不可避免,那就儘量減少裝箱和拆箱的操作,可以檢視下方簡單示例(無實際意義):

c 裝箱和拆箱

c 裝箱和拆箱 概念 裝箱 將值型別轉換為引用型別的過程叫做裝箱 值型別 引用型別 相反,拆箱 將引用型別轉換為值型別 叫做拆箱 引用型別 值型別 裝箱例子 int i 2008 object obj i console.writeline 1 i的值為,裝箱之後的值 i,obj i 927 con...

C 裝箱和拆箱

1 什麼是裝箱和拆箱 裝箱是將值型別轉換為引用型別 拆箱是將引用型別轉換為值型別 2 什麼時候需要裝箱?值型別是高效輕量的型別,因為預設情況下在堆上不包括他們的物件元件,然而,如果我們需要物件元件,這個時候就需要裝箱了。最常見的場景就是 乙個方法你希望能共用,設定的引數型別是object型別 引用型...

C 裝箱和拆箱

值型別例項進行裝箱時的步驟 1 在託管堆中分配記憶體。需要注意的是,由於是將值型別進行引用型別化,因而分配的記憶體空間除了值型別各個欄位所需的記憶體之外,還要加上託管堆所有物件都有的兩個額外成員 型別物件指標和同步塊索引 所需的記憶體。2 將值型別的字段複製到新分配的堆記憶體中。3 返回物件位址,即...