CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Raymond Lewallen

Framework Design, Agile Coach, President Oklahoma City Developers Group, Microsoft MVP C#, TDD, Continuous Integration, Patterns and Practices, Domain Driven Design, Speaker, VB.Net, C# and Sql Server

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

        a.Add(10)

    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

        a.Add(10)

        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 [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.IntegerType::FromObject(object)
      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.



Comments

Jason Haley said:

# July 29, 2005 7:30 PM

OdeToCode Links said:


Secret SQL Reporting Services Perfmon counters uncovered!

Scott C. Reynolds has a great comeback...
# July 31, 2005 6:53 PM

Daniel Moth said:

I don't really have anything to add to that post other than a couple of comments on the Intermediate Language:
# July 31, 2005 7:06 PM

Albert Smiley said:

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

Albert

# May 21, 2007 5:52 PM

Hari said:

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

# July 27, 2007 9:04 AM

Mahesh said:

excellent real world example for beginners

# November 15, 2007 2:16 PM

The boxers world » Boxing and Unboxing for Beginners said:

Pingback from  The boxers world »  Boxing  and Unboxing for Beginners

# December 6, 2007 12:45 PM

J Leonard said:

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.

# April 30, 2008 12:05 AM

Leave a Comment

(required)  
(optional)
(required)  

Enter the numbers above:
Add

About Raymond Lewallen

Working primarily in the public sector during his career, Raymond has designed and built several high profile enterprise level applications for all levels of the government. Raymond now works as a solutions architect for EMC. Raymond is an agile coach, Microsoft MVP C# and also president of the Oklahoma City Developers Group and Oklahoma Agile Developers Group. Raymond spends a lot of his time learning and teaching such things as Test Driven Development, Domain Driven Design, Design Patterns and Extreme Programming practices and principles, to name a few. Raymond is also an advocate of Alt.Net. Raymond is primarily a framework guy, so don't ask him anything about UI :) Check out Devlicio.us!