下面是關於Common Language Runtime內部的更詳細的解釋。
首先,讓我們值類型和引用類型之間的區別:
- 值類型是舉行堆棧上和它的一個副本傳遞給調用的方法
- 參考值保存在託管堆中,堆棧僅保存指向其位置的指針(引用)。的位置,而不是對象,傳遞給調用的方法
如果你不知道堆棧是什麼(不要生氣),它是保持在方法和地址局部變量的存儲區域用於return
指令的呼叫者功能(僅作簡要說明並提供一般答案)。當你調用一個方法時,堆棧上的足夠區域是靜態分配給它的,所以堆棧分配總是被稱爲靜態分配。
堆,取而代之的,是從棧中分離的存儲區域,正在運行的進程的財產,其中分配必須首先要求的操作系統,這就是爲什麼它被稱爲動態分配(如果您不要在if語句中運行,例如,可能不會爲您的進程分配內存,而是始終分配堆棧)。
只需做出最終例如在堆和棧:在語言如C++,宣告int[100] a;
堆棧(64位系統假定)上靜態地分配100 * 8個字節,而int* a = new int[100];
聲明瞭一個8個字節(上64-並且在堆上請求800個更多的字節,如果可用的話。
現在讓我們來談談C#:
拳擊
由於int是值類型,並在棧上分配,當你將它轉換爲對象或其他任何引用類型(實際上沒有其他int可以繼承的引用類型,但這是一條通用規則),該值必須成爲引用類型。因此,堆中的新區域被分配,其中的對象是盒裝的,堆棧中保存着一個指向它的指針。
拆箱
正好相反:當你有一個引用類型,如對象,並希望將其轉換爲一個值類型,如int,則新的值必須保持在棧上,所以CLR去堆,取消箱的價值,並將其複製到堆棧。
換句話說
記住int[]
和int*
的例子嗎?簡單地說,當你在C#中有int
時,運行時期望它的堆棧位置爲,其值爲,但是當你有object
時,它希望它的實際值位於堆棧指向的堆位置。
[爲什麼我們需要在C#中裝箱和拆箱?](http://stackoverflow.com/questions/2111857/why-do-we-need-boxing-and-unboxing-in-c)和[用例在C#中裝箱值類型](http://stackoverflow.com/questions/1028520/use-cases-for-boxing-a-value-type-in-c/1028549#1028549)。 – jason 2011-01-25 14:35:42
同樣重複http://stackoverflow.com/questions/13055/what-is-boxing-and-unboxing-and-what-are-the-trade-offs/25324#25324 – 2011-01-25 14:38:25