天天看點

C#之 裝箱拆箱

概念

裝箱是将值類型轉換為 object 類型或由此值類型實作的任何接口類型的過程。 當 CLR 對值類型進行裝箱時,會将該值包裝到 System.Object 内部,再将後者存儲在托管堆上。 取消裝箱将從對象中提取值類型。 裝箱是隐式的;拆箱是顯式的。 裝箱和拆箱的概念是類型系統 C# 統一視圖的基礎,其中任一類型的值都被視為一個對象。

性能

相對于簡單的指派而言,裝箱和拆箱過程需要進行大量的計算。 對值類型進行裝箱時,必須配置設定并構造一個新對象。 拆箱所需的強制轉換也需要進行大量的計算,隻是程度較輕。 有關更多資訊,請參見性能。

裝箱

裝箱用于在托管記憶體中存儲值類型。 裝箱是值類型到 object 類型或到此值類型所實作的任何接口類型的隐式轉換。 對值類型裝箱會在堆中配置設定一個對象執行個體,并将該值複制到新的對象中。

請看以下值類型變量的聲明:

int i = ;
//以下語句對變量 i 隐式應用了裝箱操作:

// Boxing copies the value of i into object o.
object o = i;  
           

此語句的結果是在堆棧上建立對象引用 o,而在堆上則引用 int 類型的值。 該值是賦給變量 i 的值類型值的一個副本。 下圖說明了兩個變量 i 和 o 之間的差異。

C#之 裝箱拆箱

裝箱轉換

還可以像下面的示例一樣執行顯式裝箱,但顯式裝箱從來不是必需的:

int i = ;
object o = (object)i;  // explicit boxing
           
class TestBoxing
{
    static void Main()
    {
        int i = ;

        // Boxing copies the value of i into object o.
        object o = i;  

        // Change the value of i.
        i = ;  

        // The change in i does not effect the value stored in o.
        System.Console.WriteLine("The value-type value = {0}", i);
        System.Console.WriteLine("The object-type value = {0}", o);
    }
}
/* Output:
    The value-type value = 
    The object-type value = 
*/
           

說明

此示例使用裝箱将整型變量 i 轉換為對象 o。 這樣一來,存儲在變量 i 中的值就從 123 更改為 456。 該示例表明原始值類型和裝箱的對象使用不同的記憶體位置,是以能夠存儲不同的值。

拆箱

是從 object 類型到值類型或從接口類型到實作該接口的值類型的顯式轉換。拆箱操作包括:

檢查對象執行個體,以確定它是給定值類型的裝箱值。

将該值從執行個體複制到值類型變量中。

下面的語句示範裝箱和拆箱兩種操作:

int i = ;      // a value type
object o = i;     // boxing
int j = (int)o;   // unboxing
           

下圖示範上述語句的結果。

C#之 裝箱拆箱

取消裝箱轉換

要在運作時成功取消裝箱值類型,被取消裝箱的項必須是對一個對象的引用,該對象是先前通過裝箱該值類型的執行個體建立的。 嘗試取消裝箱 null 會導緻 NullReferenceException。 嘗試取消裝箱對不相容值類型的引用會導緻 InvalidCastException。

class TestUnboxing
{
    static void Main()
    {
        int i = ;
        object o = i;  // implicit boxing

        try
        {
            int j = (short)o;  // attempt to unbox

            System.Console.WriteLine("Unboxing OK.");
        }
        catch (System.InvalidCastException e)
        {
            System.Console.WriteLine("{0} Error: Incorrect unboxing.", e.Message);
        }
    }
}
//此程式輸出:
//Specified cast is not valid. Error: Incorrect unboxing.
           

繼續閱讀