裝箱和拆箱
int i = 123;
object o = i;
很明顯,第2句**將值型別的資料「123」放到了乙個object型別的變數o中,而o是乙個引用型別變數,其引用的物件必須存活於託管堆中。為了解決這個問題,clr將值型別的資料「包裹」到乙個匿名的託管物件中,並將此託管物件的引用放在object型別的變數o中,這個過程稱為「裝箱(boxing)」,裝箱後物件的記憶體布局如圖4-4所示。
事實上,clr為所有的值型別變數都提供了乙個對應的「裝箱」資料型別,此資料型別其實是乙個類,擁有與值型別相同的資料和行為。
需要注意的是,裝箱之後的變數i與變數o是兩個完全獨立的變數,只是初值相同罷了,對任何乙個變數值的改變不會影響另乙個。
1 int i = 123;
2 object o = i; // 裝箱:boxing
3 int j = (int) o; // 拆箱:unboxing
上述第3句**將裝箱後的資料再「拆箱(unboxing)」,將其值賦給變數j,參見圖4-5。
「裝箱」與「拆箱」使我們可以把值型別變數看成是引用型別變數,但這個操作是耗時的,會影響程式的執行效能,因此,應該盡量避免在程式中使用裝箱與拆箱操作。
深入內幕
裝箱與拆箱的技術內幕
(1)裝箱
裝箱轉換允許將值型別(value type)變數隱式轉換為引用型別(reference type)變數。
將值型別變數的乙個值裝箱包括以下操作:分配乙個物件例項,然後將值型別變數的值複製到該例項中。
可以用以下方法理解實際裝箱過程:設想有乙個特殊的裝箱類(boxing class)。對任何值型別的型別t而言,裝箱類的行為可描述如下:
sealed class t_box: system.valuetype
t value;
public t_box(t t)
value = t;
下面的裝箱語句:
int i = 123;
object box = i;
在概念上相當於
int i = 123;
object box = new int_box(i);
實際上,像上面這樣的t_box和int_box並不存在,並且裝了箱的值的動態型別也不會真的屬於乙個類型別。相反,型別t的裝了箱的值屬於值型別t。例如:
int i = 123;
object box = i;
if (box is int) //裝箱後的變數仍是int型別
console.write("box物件包含乙個int型資料");
上述**在執行時將在控制台上輸出字串「box物件包含乙個int型資料」。
裝箱轉換隱含著複製乙份待裝箱的值。這不同於從引用型別到object型別的轉換,在後一種轉換中,轉換後的值繼續引用同一例項,只是將它當作派生程度較小的object型別而已。例如,以下**宣告了乙個值型別point。
struct point
public int x, y;
public point(int x, int y)
this.x = x;
this.y = y;
則下面的語句
point p = new point(10, 10);
object box = p;
p.x = 20;
console.write(((point)box).x);
將在控制台上輸出值10,因為將p賦值給box是乙個隱式裝箱操作,它將複製p的值。但如果將point宣告為class,由於p和box將引用同乙個例項,因此輸出值為20。
(2)拆箱
拆箱是裝箱的逆過程。
乙個拆箱操作包括以下兩個步驟:
檢查物件例項是否為給定值型別的乙個裝了箱的值。
將該值從例項中複製出來。
參照前面的例子,下面的語句
object box = 123;
int i = (int)box; //拆箱
在概念上相當於
object box = new int_box(123);
int i = ((int_box)box).value;
為了使給定值型別拆箱轉換在執行時取得成功,源運算元的值必須是對某個物件的引用,而該物件先前是通過將該值型別的某個值裝箱而建立的。
q 如果源運算元為null,則將引發system.nullreferenceexception異常。
q 如果源運算元是對不相容物件的引用,則將引發system.invalidcastexception異常。
裝箱和拆箱,自動裝箱和自動拆箱
以integer的建立為例。裝箱 把基本資料型別轉換成包裝類物件 int integer integer num1 new integer 17 拆箱 把乙個包裝類的物件,轉換成基本型別的變數 integer int int num2 num1.intvalue 自動裝箱 integer num3 ...
裝箱和拆箱
在c 中的有兩種型別的變數 值型別和引用型別。當值型別和引用型別相互轉化時,會發生裝箱和拆箱的過程。這裡有一點要宣告 經過拆箱或裝箱的物件會多出它自己乙份拷貝,如圖所示 從圖可以看出它和它的拷貝不在乙個儲存區域。這也是值型別和引用型別的區別所在。值型別總是在棧中,而引用型別總是在託管堆中。目前j2s...
裝箱和拆箱
裝箱 boxing 和拆箱 unboxing 是c 型別系統中重要的概念。它通過允許任何數值型別的資料被轉換為任何形式型別的物件提供了數值型別和引用型別間的緊密聯絡。裝箱和拆箱使得對在其中任何型別都可以最終被看作物件的型別系統的統一的觀察變為可能。裝箱轉換允許任何數值型別可以隱式地轉換為 objec...