1. 程式人生 > >裝箱和拆箱 VS 顯示轉換和隱式轉換

裝箱和拆箱 VS 顯示轉換和隱式轉換

8:對裝箱/拆箱更進一步的瞭解
裝箱/拆箱並不如上面所講那麼簡單明瞭,比如:裝箱時,變為引用物件,會多出一個方法表指標,這會有何用處呢?
我們可以通過示例來進一步探討。
舉個例子。
Struct A : ICloneable
{
public Int32 x;
public override String ToString() {
return String.Format(”{0}”,x);
}
public object Clone() {
return MemberwiseClone();
}
}
static void main()
{
A a;
a.x = 100;
Console.WriteLine(a.ToString());
Console.WriteLine(a.GetType());
A a2 = (A)a.Clone();
ICloneable c = a2;
Ojbect o = c.Clone();
}
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++的虛擬函式表指標,它是用來實現引用物件的多型機制的重要依據。