Published on

Boxing and Unboxing in .NET

Authors
  • Name
    Naito Oshima
    Twitter

Boxing and Unboxing in C# (.NET)

Boxing is the mechanism used to convert value type to reference type such us object or any interface type implemented by this value type. Unbox is the opposite.

I pick up the simplest example below. "int" is a well-known value type for 4-byte numeric value in C#.

int i = 3;
object o = i;

Variables of value type are usually stored the value on the stack.

int i = 3;

On the other hand, reference types are usually stored the actual value on the heap. So, boxing also affects their placement. Specifically, the int type value is stored in the heap and it has a pointer on the stack to refer to the box in the heap. If you look at the actual IL (Microsoft intermediate language) using Visual Studio IL Viewer or Windbg sosex debugger extension, you can see a box operations such us "IL_XXXX: box System.Int32" in action.

OpCodes.Box Field

int i1 = 3;
object o = i1;
int i2 = (int)o;

If the value on the heap pointed to by the pointer on the stack is a boxed value of the specified value type, the object is unboxed for the specified value type and store to the stack as new declared variable. If you look at the actual IL (Microsoft intermediate language) using something like Windbg sosex debugger extension, you can see a box operations such us "IL_XXXX: unbox.any System.Int32" in action.

OpCodes.Unbox_Any Field

Note that if the type is specified incorrectly, an InvalidCastException will occur.

On top of that, there are a bit differnce between unbox operation and unbox.any operation as ECMA-335 said.

Unlike the unbox instruction, for value types, unbox.any leaves a value, not an address of a value, on the stack.

(III.4.33 unbox.any – convert boxed type to value in ECMA-335 (The Common Language Infrastructure))

Checking internal about stack and heap through memory dumps when Boxing or Non-boxing

After storing a boxing variable for wrapping an pre-defined int variable, it seems to be the managed stack has the pointer of int value.

0:000> !sos.clrstack -i local_1 1
...
LOCALS:
  + int local_0  = 3
  + System.Int32 local_1 @ 0x1660000b200
     |- int m_value  = 3
...

0:000> !mex.dumpheap2
Address Gen Size  Type Data
================
...
000001660000b1f8   0    24 System.Int32
...

0:000> !mex.DisplayObj 000001660000b1f8 -comment System.Int32
000001660000b1f8 System.Int32
3

Meanwhile, after storing a non-boxing variable, the managed stack doesn't have the pointer of System.Int32 value. When executing !mex.dumpheap2, there should be no object in the heap containing the 3 value of type int.

For your information about fundamental boxing and unboxing, Microsoft formal Site about it is the following article to see that.

ref.) C# - Boxing and Unboxing