I want to begin the series by covering some “advanced basics”. You can find a million “Hello World” tutorials, so I want to avoid those and cover topics frequently overlooked in beginners books. Boxing is just such a topic.
As you may be aware, there are two kinds of variables in .Net, value types and reference types. A value type is stored in an area of memory called the stack, which is a very fast place to get to. Value types are simple data types like integers, doubles, and so on. Things the compiler can always guarantee the size of.
Reference types, on the other hand have a variable size, and thus don’t fit nicely on the stack. So .Net puts them in a memory location called the heap, and stores a reference to the stack.
It’s a lot like having a post office box. For small items, like letters, you just go to the post office box and remove them, quick and easy. Let’s say you get a huge package, maybe that spiffy new laptop has finally arrived. Obviously that laptop won’t fit in your post office box, so the mail service puts a little yellow slip that says “you’ve got a package, it’s stored in this location, come get it”.
The post office box in this case would be the stack. Letters are like value types, small, fast to get to, and usually one of a few predictable sizes. The little yellow slip saying you’ve got a package would be a reference type, it’s pointing to a specific spot in the heap of packages stored in the back room.
Now, boxing occurs whenever you try to put a value type, such as an integer, into a reference type, such as an object.
int myLetter = 42;
object myBox = (object)myLetter;
Because .Net doesn’t know in advance how big the myBox object will be, it has to make it a reference type. Placing an int into it makes no difference. .Net will happily take the value 42, place it on the heap, and store a reference to the memory location in the myBox variable.
As you might guess, extending our PO Box analogy would have the post office take the letter out of your PO Box, shove it in a big box, put it in the back and stick one of those yellow slips in your slot.
This entire process is called Boxing. The reverse, putting a refernce type back into an value type is called Unboxing.
object myBox = 42;
int myLetter = (int)myBox;
Boxing and unboxing are very slow processes. Additionally, they are fraught with danger. What if we’d tried this instead?
object myBox = 3.1415719;
int myLetter = (int)myBox;
Gold star to anyone who blurted out “run time error” or “invalid cast exception”. There is no implicit type checking when moving from a value type back to a reference. You will have to add additional code to be sure that no errors happen.
In general you should try to avoid boxing and unboxing, and instead use generics (more on them later). Occasionally you can’t avoid it, for example:
// Some code here that loads records and increments recordCount
MessageBox.Show(“You loaded “ + recordCount.ToString()
+ ” records.”);
You may not realize it, but when you call ToString, you are creating a boxing operation, converting our nice value type int into a reference type string. As I mentioned, sometimes you can’t avoid these types of operations. Which brings us to the obvious question, when is it “safe” to box?
Typically when you perform a widening operation, moving a smaller variable into a larger one, you’re OK. For instance, moving an int into a double or string is safe because you are taking a smaller data type and moving it to a larger one. Much like taking an envelope out of your post office box, and placing into one of those large overnight mailers, or a shipping carton.
A narrowing conversion on the other hand is when you take a big variable and try to shove it into a smaller one, such as a double into an int. These are dangerous and you should be sure what you are doing before attempting.
By the way, not all widening operations are necessarily a boxing operation. Going from int to double is widening, but not boxing because there are two value types involved. Moving from int to string is both widening and boxing, as you are going from a value to a reference type. Whichever the case, just know that both are “safe” things to do. You can rest easy knowing this particular type of operation is safe.
Boxing is one of those arcane pieces of knowledge, understanding it will help you to be a better programmer so you will know when using it appropriately, and when to avoid it.