Boxing and Unboxing for Beginners

Value types are created on the stack.  Reference types are
created on the heap.  When something is created on the heap (an
object) the variable assigned to that object holds a 4 byte “pointer”
to the address space on the heap where the object has been
allocated.  Every time you pass that variable as a parameter to
another method, the 4 byte pointer is passed, not the object
itself.  When you pass a value type (Integer, DateTime and such),
a copy is made and the entire value type is copied to the method where
its going to be used.

In the near future, I have a post in the making on using value types versus reference types.

Sometimes, you need to use a value type as if it were a
reference type.  This is known as “boxing”.  Let’s say you
wanted to create an arraylist that contains Integers.

    Public Sub Method1()

        Dim a As New ArrayList


    End Sub

If you examine the Add method of an arraylist, you see that it is
not overloaded.  It only take System.Object as a parameter. 
System.Object is a reference type is any objects are created on the
heap.  In the first paragraph, we know that Int32 is a value
type.  So what happens when we add an integer to an
arraylist?  Let’s look at the MSIL

.method public instance void Method1() cil managed
      // Code Size: 23 byte(s)
      .maxstack 2
      .locals (
            [mscorlib]System.Collections.ArrayList list1)
      L_0000: nop
      L_0001: newobj instance void [mscorlib]System.Collections.ArrayList::.ctor()
      L_0006: stloc.0
      L_0007: ldloc.0
      L_0008: ldc.i4.s 10
      L_000a: box int32
      L_000f: callvirt instance int32 [mscorlib]System.Collections.ArrayList::Add(object)
      L_0014: pop
      L_0015: nop
      L_0016: ret

At L_0008, you see that we load the 4 byte integer 10 to the stack,
you see the IL instruction to box that value as the next
instruction.  So what is actually being stored in the
arraylist?  Well we know that since arraylist takes an object as
its parameter, we know that it wants to store an address pointer, not
the value ‘10’.  In order to get an address pointer to store in
the arraylist, the integer has to be converted to an object and a
reference to that object must be obtained.  This is called boxing.

So what is really happening during boxing?  Just like any
object, memory on the heap must be allocated for the object.  The
Int32’s information is then copied to that new address space.  The
address pointer of that location where the Int32’s information was
copied to is returned.  The Int32, a native value type, is now an
object: a reference type.  That address pointer is what actually
gets passed to the Add method of the arraylist.

So what about unboxing?  Unboxing is the exact opposite of boxing.

    Public Sub Method1()

        Dim a As New ArrayList


        Dim b As Int32

        b = a(0)

    End Sub

In this code, we create an Int32 and want to store the value from
the first element of the arraylist to this Integer, in this case
‘10’.  Unboxing is defined as getting the address of the object,
and then copying that information to a value type that has been created
on the stack (b in the above example).  The MSIL is below:

.method public instance void Method1() cil managed
      // Code Size: 36 byte(s)
      .maxstack 2
      .locals (
            [mscorlib]System.Collections.ArrayList list1,
            int32 num1)
      L_0000: nop
      L_0001: newobj instance void [mscorlib]System.Collections.ArrayList::.ctor()
      L_0006: stloc.0
      L_0007: ldloc.0
      L_0008: ldc.i4.s 10
      L_000a: box int32
      L_000f: callvirt instance int32 [mscorlib]System.Collections.ArrayList::Add(object)
      L_0014: pop
      L_0015: ldloc.0
      L_0016: ldc.i4.0
      L_0017: callvirt instance object [mscorlib]System.Collections.ArrayList::get_Item(int32)
L_001c: call int32
      L_0021: stloc.1
      L_0022: nop
      L_0023: ret

You can see at instruction L_001c, the FromObject method is
called.  This does the work of unboxing that we mentioned
above.  2 imporant exceptions to take note of when unboxing
though.  If the reference that are “getting” from the arraylist is
nothing, a NullReferenceException will occur. 
If the reference type that you are “getting” isn’t an Int32 in the
above example, let’s say its a System.DateTime, then a InvalidCastException will occur.

So you’ve probably heard to avoid boxing and unboxing when you
can.  Why?  Obviously, its costly to the speed and memory of
your application.  Extra instructions and memory space are
required when boxing and unboxing.  Also when you box a value type
(recall this required allocating memory space on the heap), you always
risk having the garbage collector run against the heap to clean up
unused resources, which is an expensive operation.

This entry was posted in .Net Development, Most Popular. Bookmark the permalink. Follow any comments here with the RSS feed for this post.

6 Responses to Boxing and Unboxing for Beginners

  1. Aj says:

    Why only Boxed type are unboxed? Any idea.

  2. J Leonard says:

    This is NOT for beginners. To read this article you need to have a very deep understanding of Assembly language, stacks, heaps, and C#. Nowhere is it explain WHY you would want to box or unbox. What’s the whole point? Who knows.

  3. Mahesh says:

    excellent real world example for beginners

  4. Hari says:

    Hi thanks for your comments in boxing and unboxing am a beginer to this concept can you mail me about this in detail am very much interested in it

  5. I am really interested in boxing and I don’t really know where to begin. Please advise and send to the email above. Thank you in advance

Leave a Reply