Boxing 和 Unboxing (C# 程式設計手冊)Boxing and Unboxing (C# Programming Guide)

Boxing 是將實值型別轉換為 object 類型或是由這個實值型別實作之任何介面類型的程序。Boxing is the process of converting a value type to the type object or to any interface type implemented by this value type. 當 CLR Box 處理實值類型時,它會將值包裝在 System.Object 內,並儲存到 Managed 堆積上。When the CLR boxes a value type, it wraps the value inside a System.Object and stores it on the managed heap. Unbox 處理則會從物件中擷取實值類型。Unboxing extracts the value type from the object. Boxing 是隱含處理,unboxing 則是明確處理。Boxing is implicit; unboxing is explicit. Boxing 和 unboxing 的概念是 C# 類型系統統一檢視的基礎,其中任何類型的值都可視為物件。The concept of boxing and unboxing underlies the C# unified view of the type system in which a value of any type can be treated as an object.

在下列範例中,整數變數 i 會經過 Box 處理並且指派給 o 物件。In the following example, the integer variable i is boxed and assigned to object o.

int i = 123;
// The following line boxes i.
object o = i;  

接著就可以對物件 o 進行 Unbox 處理,並將該物件指派給整數變數 iThe object o can then be unboxed and assigned to integer variable i:

o = 123;
i = (int)o;  // unboxing

下列範例將說明在 C# 中使用 boxing 的方式。The following examples illustrate how boxing is used in C#.

// String.Concat example.
// String.Concat has many versions. Rest the mouse pointer on 
// Concat in the following statement to verify that the version
// that is used here takes three object arguments. Both 42 and
// true must be boxed.
Console.WriteLine(String.Concat("Answer", 42, true));


// List example.
// Create a list of objects to hold a heterogeneous collection 
// of elements.
List<object> mixedList = new List<object>();

// Add a string element to the list. 
mixedList.Add("First Group:");

// Add some integers to the list. 
for (int j = 1; j < 5; j++)
{
    // Rest the mouse pointer over j to verify that you are adding
    // an int to a list of objects. Each element j is boxed when 
    // you add j to mixedList.
    mixedList.Add(j);
}

// Add another string and more integers.
mixedList.Add("Second Group:");
for (int j = 5; j < 10; j++)
{
    mixedList.Add(j);
}

// Display the elements in the list. Declare the loop variable by 
// using var, so that the compiler assigns its type.
foreach (var item in mixedList)
{
    // Rest the mouse pointer over item to verify that the elements
    // of mixedList are objects.
    Console.WriteLine(item);
}

// The following loop sums the squares of the first group of boxed
// integers in mixedList. The list elements are objects, and cannot
// be multiplied or added to the sum until they are unboxed. The
// unboxing must be done explicitly.
var sum = 0;
for (var j = 1; j < 5; j++)
{
    // The following statement causes a compiler error: Operator 
    // '*' cannot be applied to operands of type 'object' and
    // 'object'. 
    //sum += mixedList[j] * mixedList[j]);

    // After the list elements are unboxed, the computation does 
    // not cause a compiler error.
    sum += (int)mixedList[j] * (int)mixedList[j];
}

// The sum displayed is 30, the sum of 1 + 4 + 9 + 16.
Console.WriteLine("Sum: " + sum);

// Output:
// Answer42True
// First Group:
// 1
// 2
// 3
// 4
// Second Group:
// 5
// 6
// 7
// 8
// 9
// Sum: 30

效能Performance

相對於單純的指派,boxing 和 unboxing 是會耗費大量運算資源的處理序。In relation to simple assignments, boxing and unboxing are computationally expensive processes. 當實值類型經過 Box 處理時,必須配置及建構新的物件。When a value type is boxed, a new object must be allocated and constructed. Unboxing 所需的轉換雖然較為簡單,但也同樣需要大量運算資源。To a lesser degree, the cast required for unboxing is also expensive computationally. 如需詳細資訊,請參閱效能For more information, see Performance.

BoxingBoxing

Boxing 可用來儲存記憶體回收堆積中的實值類型。Boxing is used to store value types in the garbage-collected heap. Boxing 是一種隱含轉換,可將實值型別轉換為 object 類型,或是由這個實值型別實作的任何介面類型。Boxing is an implicit conversion of a value type to the type object or to any interface type implemented by this value type. 對實值類型進行 Boxing 處理時,會在堆積上配置物件執行個體,並將值複製到新物件中。Boxing a value type allocates an object instance on the heap and copies the value into the new object.

請考慮下列實值類型變數的宣告:Consider the following declaration of a value-type variable:

int i = 123;

下列陳述式會以隱含方式對變數 i 套用 boxing 作業:The following statement implicitly applies the boxing operation on the variable i:

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

這個陳述式的結果是在堆疊上建立物件參考 o,用於參考堆積中 int 類型的值。The result of this statement is creating an object reference o, on the stack, that references a value of the type int, on the heap. 這個值是指派給變數 i 之實值類型值的複本。This value is a copy of the value-type value assigned to the variable i. io 這兩個變數之間的差異如下方 Boxing 轉換圖所示:The difference between the two variables, i and o, is illustrated in the following image of boxing conversion:

顯示 i 和 o 變數之間差異的圖形。

您也可以執行明確的 boxing 處理,如同下列範例中所示,但是明確的 boxing 處理並非必要:It is also possible to perform the boxing explicitly as in the following example, but explicit boxing is never required:

int i = 123;
object o = (object)i;  // explicit boxing

說明Description

這個範例會使用 Boxing 將整數變數 i 轉換為物件 oThis example converts an integer variable i to an object o by using boxing. 接著,儲存在變數 i 中的值就會從 123 變更為 456Then, the value stored in the variable i is changed from 123 to 456. 這個範例顯示,原始實值類型以及經過 Box 處理的物件分別使用不同的記憶體位置,因此可以儲存不同的值。The example shows that the original value type and the boxed object use separate memory locations, and therefore can store different values.

範例Example

class TestBoxing
{
    static void Main()
    {
        int i = 123;

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

        // Change the value of i.
        i = 456;  

        // The change in i doesn't affect 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 = 456
    The object-type value = 123
*/

UnboxingUnboxing

Unboxing 是將 object 類型明確轉換為實值型別,或將介面類型明確轉換為實作介面之實值型別的程序。Unboxing is an explicit conversion from the type object to a value type or from an interface type to a value type that implements the interface. Unboxing 作業包含:An unboxing operation consists of:

  • 檢查物件執行個體,確定它是所指定實值類型經過 Box 處理的值。Checking the object instance to make sure that it is a boxed value of the given value type.

  • 將值從執行個體複製到實值類型變數。Copying the value from the instance into the value-type variable.

下列陳述式將示範 boxing 和 unboxing 作業:The following statements demonstrate both boxing and unboxing operations:

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

下圖示範上述陳述式的結果:The following figure demonstrates the result of the previous statements:

顯示 Unboxing 轉換的圖形。

若要在執行階段成功對實值類型進行 Unbox 處理,要進行 Unbox 處理的項目必須是物件的參考,而且該物件是先前對該實值類型的執行個體進行 Box 處理所建立的物件。For the unboxing of value types to succeed at run time, the item being unboxed must be a reference to an object that was previously created by boxing an instance of that value type. 嘗試對 null 進行 Unbox 處理會造成 NullReferenceExceptionAttempting to unbox null causes a NullReferenceException. 嘗試對不相容的實值類型參考進行 Unbox 處理會造成 InvalidCastExceptionAttempting to unbox a reference to an incompatible value type causes an InvalidCastException.

範例Example

下列範例將示範 Unboxing 無效且產生 InvalidCastException 的案例。The following example demonstrates a case of invalid unboxing and the resulting InvalidCastException. 若使用 trycatch,則會在發生錯誤時顯示錯誤訊息。Using try and catch, an error message is displayed when the error occurs.

class TestUnboxing
{
    static void Main()
    {
        int i = 123;
        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);
        }
    }
}

這個程式會輸出:This program outputs:

Specified cast is not valid. Error: Incorrect unboxing.

如果您將陳述式:If you change the statement:

int j = (short) o;  

變更為:to:

int j = (int) o;  

轉換將會執行,而且您會得到下列輸出結果:the conversion will be performed, and you will get the output:

Unboxing OK.

C# 語言規格C# Language Specification

如需詳細資訊,請參閱<C# 語言規格>。For more information, see the C# Language Specification. 語言規格是 C# 語法及用法的限定來源。The language specification is the definitive source for C# syntax and usage.

如需詳細資訊:For more information:

另請參閱See also