Boxing

A value type is descended from object and hence can be caste to object - but object is a reference type and this raises the question of exactly what happens. The answer is that a new object containing the value type is created on the heap a process called boxing.

For example suppose you have defined a method something like:

void DoIt(object x){ ..}

What happens when you pass a simple value type. As value types are descended from “object” so that there is no reason why you can’t pass an int say.

The problem is that on the inside of the method the variable “x” is treated using reference semantics and if you pass a value type by value this is going to be a problem. Whenever you either explicitly or implicitly cast a value type to a reference type then the value type is converted to or “boxed” by its hidden reference type. For example, if you write:

void DoIt(object x){ object y; y=x;

and then call the method using:

int I=10;DoIt(I);

then y points to the same int object that x does. A small confusion is that the dynamic type of both x and y is int, as a boxed type has the same type as the corresponding value type. As you can imagine to make this work involves at least the creation of internal reference to the int and this all takes time.

To unbox a value type you have to use an explicit caste as in:

int j=(int) x;

You can box and unbox all of the simple types and structs.

There is one final twist to the story, however, which is another enforcement of value type semantics. When a value type is boxed a complete copy of the value is made and not just a reference to the value. For example, following:

int I=10;object x=I;I=20

what do you think the value of x is? If x is just a reference to I then it should be 20 but in fact it is still 10 because a copy of the value in I is made when the variable is boxed. The same sort of thing happens when you box a struct. For example:

PointV p=new PointV();p.x=10;object q=p;p.x=20

In this is case when the assignment q=p is made p is boxed and a new copy of the data is created and so the assignment p.x=20 doesn’t change the value of q.x. Notice that every time you assign a value type a new object is created on the heap. So for example,

int I=10;object a = I;object b = a;

sets both a and b referencing the same object on the heap with the integer value 10. Following:

a = 20;

you might think that b now also points to an object on the heap containing 20 but the assignment creates a new object on the heap containing 20 and only a reference this. The result is that I has the value 10, a has the value 20 and b still has the value 10.

Boxing and the reverse process unboxing can occur in situations when you don’t even notice it happening. The most used example of this is WriteLine which takes an object as its parameter. Hence when you use it to display a simple integer:

Console.WriteLine(I);

a boxing operation occurs. Within the WriteLine method i.ToString is called to obtain a displayable form and you can avoid the boxing operation by simply passing a string in the first place:

Console.WriteLine(i.ToString());

Obviously boxing an unboxing take time and have the potential to slow your program down and it should be avoided if possible. In the past it was difficult to avoid because of the need to use object types within classes that implemented data structures so that they could work with as many types of element as possible.

For example, the ArrayList data structure has an Add method that accepts a parameter of type object. Hence if you build an ArrayList of integers say each one will be boxed as you use Add to add it to the data structure.

The same sort of problem arrises with any data structure that used object types to make sure it works with almost anything. The solution is not to implement data structures in this way but use a generic class that can be typed appropriately when you use it. Of course this doesn’t help if you need a data structure which stores a set of mixed types - in this case boxing and unboxing value types might be your only option.