C 裝箱與拆箱

2021-07-04 05:45:10 字數 2574 閱讀 4939

裝箱是將

值型別轉換為

引用型別

;拆箱是將

引用型別

轉換為值型別

利用裝箱和拆箱功能,可通過允許

值型別的任何值與

object 型別

的值相互轉換,將值型別與引用型別鏈結起來 

例如: 

int val = 100; 

object obj = val; 

console.writeline (「物件的值 = ", obj); 

這是乙個裝箱的過程,是將

值型別轉換為

引用型別

的過程 

int val = 100; 

object obj = val; 

int num = (int) obj; 

console.writeline ("num: ", num); 

這是乙個拆箱的過程,是將值型別轉換為引用型別,再由引用型別轉換為值型別的過程 

注:被裝過箱的物件才能被拆箱

裝箱/拆箱的內部操作。

裝箱: 

對值型別在堆中分配乙個物件例項,並將該值複製到新的物件中。按三步進行。 

第一步:新分配託管堆記憶體(大小為值型別例項大小加上乙個方法表指標和乙個syncblockindex)。 

第二步:將值型別的例項字段拷貝到新分配的記憶體中。 

第三步:返回託管堆中新分配物件的位址。這個位址就是乙個指向物件的引用了。 

有人這樣理解:如果將int32裝箱,返回的位址,指向的就是乙個int32。我認為也不是不能這樣理解,但這確實又有問題,一來它不全面,二來指向int32並沒說出它的實質(在託管堆中)。 

拆箱:檢查物件例項,確保它是給定值型別的乙個裝箱值。將該值從例項複製到值型別變數中。 

有書上講,拆箱只是獲取引用物件中指向值型別部分的指標,而內容拷貝則是賦值語句之觸發。我覺得這並不要緊。最關鍵的是檢查物件例項的本質,拆箱和裝箱的型別必需匹配,這一點上,在il層上,看不出原理何在,我的猜測,或許是呼叫了類似gettype之類的方法來取出型別進行匹配(因為需要嚴格匹配)。

對裝箱/拆箱更進一步的了解

裝箱/拆箱並不如上面所講那麼簡單明瞭,比如:裝箱時,變為引用物件,會多出乙個方法表指標,這會有何用處呢? 

我們可以通過示例來進一步**。 

舉個例子。 

struct a : icloneable 

」,x); 

} public object clone()  

} static void main() 

5.0:a.tostring()。編譯器發現a重寫了tostring方法,會直接呼叫tostring的指令。因為a是值型別,編譯器不會出現多型行為。因此,直接呼叫,不裝箱。(注:tostring是a的基類system.valuetype的方法) 

5.1:a.gettype(),gettype是繼承於system.valuetype的方法,要呼叫它,需要乙個方法表指標,於是a將被裝箱,從而生成方法表指標,呼叫基類的system.valuetype。(補一句,所有的值型別都是繼承於system.valuetype的)。 

5.2:a.clone(),因為a實現了clone方法,所以無需裝箱。 

5.3:icloneable轉型:當a2為轉為介面型別時,必須裝箱,因為介面是一種引用型別。 

5.4:c.clone()。無需裝箱,在託管堆中對上一步已裝箱的物件進行呼叫。 

附:其實上面的基於乙個根本的原理,因為未裝箱的值型別沒有方法表指標,所以,不能通過值型別來呼叫其上繼承的虛方法。另外,介面型別是乙個引用型別。對此,我的理解,該方法表指標類似c++的虛函式表指標,它是用來實現引用物件的多型機制的重要依據。

如何更改已裝箱的物件

對於已裝箱的物件,因為無法直接呼叫其指定方法,所以必須先拆箱,再呼叫方法,但再次拆箱,會生成新的棧例項,而無法修改裝箱物件。有點暈吧,感覺在說繞口令。還是舉個例子來說:(在上例中追加change方法) 

public void change(int32 x)  

呼叫: 

a a = new a(); 

a.x = 100; 

object o = a; //裝箱成o,下面,想改變o的值。 

((a)o).change(200); //改掉了嗎?沒改掉。 

沒改掉的原因是o在拆箱時,生成的是臨時的棧例項a,所以,改動是基於臨時a的,並未改到裝箱物件。 

(附:在託管c++中,允許直接取加拆箱時第一步得到的例項引用,而直接更改,但c#不行。) 

那該如何是好? 

嗯,通過介面方式,可以達到相同的效果。 

實現如下: 

inte***ce ichange  

struct a : ichange  

呼叫: 

((ichange)o).change(200);//改掉了嗎?改掉了。 

為啥現在可以改? 

在將o轉型為ichange時,這裡不會進行再次裝箱,當然更不會拆箱,因為o已經是引用型別,再因為它是ichange型別,所以可以直接呼叫change,於是,更改的也就是已裝箱物件中的字段了,達到期望的效果。

C 裝箱與拆箱

要掌握裝箱與拆箱,就必須了解cts及它的特點。net重要技術和基礎之一的cts common type system 顧名思義,cts就是為了實現在應用程式宣告和使用這些型別時必須遵循的規則而存在的通用型別系統。net將整個系統的型別分成兩大類 value type 和 reference type...

C 裝箱與拆箱

在前面提到了值型別和引用型別。這裡就來和大家一起了解一下,他們互相轉換的過程裝箱 boxing 拆箱 unboxing 由於c 中所有的資料型別都是由基類system.object繼承而來的,所以值型別和引用型別的值可以通過顯式 或隱式 操作相互轉換,而這轉換過程也就是裝箱 boxing 和拆箱 u...

C 裝箱與拆箱

在生活中,我們都喜歡吃水果。大家都知道水果不但為我們提供豐富的膳食纖維,還有維生素及其它營養。例如 吃士多啤梨培養耐心補充維生素,吃香蕉保持快樂心情,吃葡萄增強免疫抗衰老,吃梨幫助器官排毒等等,所有我們經常去買水果,而一般水果都是裝在箱子裡,廠商把水果裝箱賣給經銷商,經銷商在拆箱賣給我們。這就是生活...