概念
裝箱是将值類型轉換為 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 之間的差異。
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicWZwpmL4UDN2czQJ9CXn1WaulHZvwVbvNmL0Z2ct1ycuMWZz5ibkNXbtk2Lc9CX6MHc0RHaiojIsJye.jpeg)
裝箱轉換
還可以像下面的示例一樣執行顯式裝箱,但顯式裝箱從來不是必需的:
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
下圖示範上述語句的結果。
取消裝箱轉換
要在運作時成功取消裝箱值類型,被取消裝箱的項必須是對一個對象的引用,該對象是先前通過裝箱該值類型的執行個體建立的。 嘗試取消裝箱 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.