CHAPTER 9 COLLECTIONS AND GENERICS
Although you pass in numerical data directly into methods requiring an object, the runtime
automatically boxes the stack-based data on your behalf. Later, if you want to retrieve an item from the
ArrayList using the type indexer, you must unbox the heap-allocated object into a stack-allocated
integer using a casting operation. Remember that the indexer of the ArrayList is returning
System.Objects, not System.Int32s:
static void WorkWithArrayList()
{
// Value types are automatically boxed when
// passed to a member requesting an object.
ArrayList myInts = new ArrayList();
myInts.Add(10);
myInts.Add(20);
myInts.Add(35);
// Unboxing occurs when a object is converted back to
// stack-based data.
int i = (int)myInts[0];
}
// Now it is reboxed, as WriteLine() requires object types!
Console.WriteLine("Value of your int: {0}", i);
Again, note that the stack-allocated System.Int32 is boxed prior to the call to ArrayList.Add(), so it
can be passed in the required System.Object. Also note that the System.Object is unboxed back into a
System.Int32 once it is retrieved from the ArrayList via the casting operation, only to be boxed again
when it is passed to the Console.WriteLine() method, as this method is operating on System.Object
variables.
Boxing and unboxing are convenient from a programmer’s viewpoint, but this simplified approach
to stack/heap memory transfer comes with the baggage of performance issues (in both speed of
execution and code size) and a lack of type safety. To understand the performance issues, ponder the
steps that must occur to box and unbox a simple integer.
1.
A new object must be allocated on the managed heap.
2.
The value of the stack-based data must be transferred into that memory
location.
3.
When unboxed, the value stored on the heap-based object must be transferred
back to the stack.
4.
The now unused object on the heap will (eventually) be garbage collected.
Although this particular WorkWithArrayList() method won’t cause a major bottleneck in terms of
performance, you could certainly feel the impact if an ArrayList contained thousands of integers that
your program manipulates on a somewhat regular basis. In an ideal world, you could manipulate stackbased data in a container without any performance issues. Ideally, it would be nice if you did not have to
have to bother plucking data from this container using try/catch scopes (this is exactly what generics let
you achieve).
329