Recently someone asked me a question that any first year Computer Science major could answer without blinking an eye. But for those of us who have been out of school for a while have to stop, think, have a brain freeze, and finally go Google it. In the end you knew what it meant but had forgotten the terms. Here is the question that was asked, ‘what is boxing and unboxing?’ This post is the first in a series of post where I will attempt to channel my college days to refresh my memory of "All that CS stuff that you know about but have forgotten"
To under stand boxing and unboxing you first have to understand the difference between a value type and a reference type. In simple terms a value type is a variable that directly stores a value. They live on the stack for quick and easy access. Reference types are a little more beefier and include things like objects. These live on the managed heap and are subjected to garbage collecting.
Let’s now talk about instantiation. Value types are created on the stack and are readily available. When you set a value type equal to another value type the value stored in the first locations is copied to the location of the second value. When you instantiate a reference type enough space is allocated on the heap to store that object. If you set an object equal to another object a reference to the object on the heap is assigned to the second object. In other words only one object lives on the heap and the two variables are pointing to the same object.
So where do these boxes come in? Well when you assign a value type to a reference type (usually an object) you are boxing. This can be done implicitly like in the following code:
//Implicit boxing
int i = 234;
object o = i;
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
or explicitly:
//Explicitly boxing
int i = 234;
object o = (object)i;.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
If boxing is going from value type to reference type then going the other way must be unboxing. Unboxing must all ways be done explicitly:
//Explicitly unboxing
int j = (int)o;
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
There are some some concerns when unboxing. First the object must of the same type as the variable you are casting it to. Next you must make sure it fits, especially with numeric values (i.e. int32 to an int16), in order to avoid errors. Finally the reference type cannot be null. This will cause a InvalidCastException.
Now that we have the definition of boxing and unboxing let’s discuss when this may happen. The most common instance that I can come up with is when you implicitly pass a value type to a method with the following signature:
public void SomeMethod(object o)
So why do we care. When you box a value type a new object is instantiated on the managed heap. When unboxing to a value type a conversion takes place. Both of these have performance implications and should be avoided if at all possible. Doing this type of operation once may not hurt you. Doing it thousands of times may really impact the performance. This is one of thing that you can look for when troubleshooting performance issues.
As I stated at the beginning of this post, this was a concept I knew and put into practice many times but had forgotten about the principals behind it. I will continue to add post like this on a regular basis. We can all use a little reminder.
Reference: http://msdn.microsoft.com/en-us/library/yz2be5wk(VS.80).aspx
Leave a Reply