SoFunction
Updated on 2025-03-07

Detailed explanation of parsing packing and unboxing in C#

Boxing and unboxing are the operations to be performed between value types and reference types.
1. Boxing occurs when the value type is converted to the reference type
2. Unboxing occurs when the reference type is converted to value type
The above two sentences are not difficult to understand, but to understand them deeply, it takes some time to explain them.
Let's first look at what happens when packing. Here is a line of simplest packing code
Copy the codeThe code is as follows:

object obj = 1;

This line of statement assigns the integer constant 1 to the variable obj of type object; as we all know, constant 1 is a value type, the value type is placed on the stack, and object is a reference type, which needs to be placed on the heap; to place the value type on the heap, a boxing operation is required.
The IL code of this line statement is as follows, please pay attention to the comments section:
Copy the codeThe code is as follows:

.locals init (
  [0] object objValue
) //The above three lines of IL represent local variables that declare object type name objValue
IL_0000: nop
IL_0001: ldc. 9 // means to put integer number 9 on the top of the stack
IL_0003: box [mscorlib]System.Int32 //Execute the IL box instruction and apply for the heap space required by the System.Int32 type in the memory heap
IL_0008: stloc.0 //Pop up the variable on the stack and store it in a local variable with index 0

The above is what boxing needs to be performed. When performing boxing operations, it is inevitable to apply for memory space on the heap and copy the value type data on the stack to the applied heap memory space. This will definitely consume memory and CPU resources.Let's take a look at what the unboxing operation is:
Please see the following C# code:
Copy the codeThe code is as follows:

object objValue = 4;
int value = (int)objValue;

The above two lines of code will perform a boxing operation to box the shaping number constant 4 into the reference type object variable objValue; then perform another unboxing operation to store the reference variable objValue stored on the heap into the local shaping value type variable value.
Also, we need to look at the IL code:
Copy the codeThe code is as follows:

.locals init (
  [0] object objValue,
  [1] int32 'value'
) //The above IL declares two local variables object type objValue and int32 type value variable
IL_0000: nop
IL_0001: ldc.i4.4 //Press integer number 4 into the stack
IL_0002: box [mscorlib]System.Int32 //Execute the IL box instruction and apply for the heap space required by the System.Int32 type in the memory heap
IL_0007: stloc.0 //Pop up the variable on the stack and store it in a local variable with index 0
IL_0008: ldloc.0//Press local variables (i.e. objValue variables) with index 0 onto the stack
IL_0009: [mscorlib]System.Int32 //Execute the IL unboxing instruction to convert the reference type object to the System.Int32 type
IL_000e: stloc.1 //Storage the data on the stack to a local variable with index 1, i.e. value

The execution process of unboxing operation is exactly the opposite of the packing operation, which is to convert the reference type value stored on the heap into a value type and give the value type variable.
Boxing and unboxing operations require additional CPU and memory resources, so generics were introduced after C# 2.0 to reduce the consumption of boxing and unboxing operations.