.NET 中的裝箱與拆箱實現過程

高洛峰
發布: 2017-01-24 14:17:33
原創
1155 人瀏覽過

先看下面的程式碼: 

int tempi = 1; 
object o = tempi; 
double tempd = (double) o;
登入後複製

編譯時可以通過,但執行時間卻報以下錯誤: 
System.InvalidCastException: 指定的轉換無效。 

這是因為,當對一個物件進行拆箱時,轉換的結果必須是它原來未裝箱的類型。此處必須先轉換為int型,才能再轉換為double型別。其正確格式如下: 

int tempi = 32; 
object o = tempi; 
double tempd = (double)(int) o;
登入後複製

在.NET框架中,裝箱(boxing)通常由以下三步驟組成: 
1.從託管堆中為新產生的引用類型物件分配記憶體。指派的記憶體大小為被裝箱的值型別實例本身的大小,再加上為新產生的參考型別新增的一個方法表指標和一個SyncBlockIndex。 
2.將值類型實例的欄位拷貝到託管堆上新分配物件的記憶體。 
3.傳回託管堆中新分配物件的位址。這樣值型別實例也變成了一個引用型別物件。 

而拆箱(unboxing)過程則如下: 
1.如果要拆箱的物件為null,將會拋出一個NullReferenceException例外。 
2.如果該引用指向的對像不是一個期望的值類型的已裝箱對象,則拆箱失敗,並拋出一個InvalidCastException異常(如本文剛開始的部分)。 
3.一個指向包含在已經裝箱物件中值類型部分的指標被回傳。此指標所指向的值類型對於引用型別物件通常所具有的附加成員(即一個方法表指標和一個SyncBlockIndex)一無所知。實際上,該指標指向的是已經裝箱物件中的未裝箱部分(Microsoft.NET 框架程式設計)。

對於第3點,可以使用上面的範例來幫助理解。首先定義值類型變數tempi,它在記憶體中佔用4個字節,裝箱之後,其變成引用物件的同時,增加了一個方法表指標和一個SyncBlockIndex。對於引用類型而言,只需要傳一個「引用類型」的位址,就可以得到其值、方法表指標和SyncBlockIndex。在拆箱時,傳遞的是其「值」的位址(未裝箱的部分),即一個「int(Int32)類型」的位址(引用),它只允許讀4個位元組。而double類型是8個位元組,因此隱式的轉換是會報錯的,需要先將其轉換成int型別後,才能再轉換為double型別。

更多.NET 中的裝箱與拆箱實現過程相關文章請關注PHP中文網!

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!