CHAPTER 9 COLLECTIONS AND GENERICS
static void SimpleBoxUnboxOperation()
{
// Make a ValueType (int) variable.
int myInt = 25;
// Box the int into an object reference.
object boxedInt = myInt;
}
// Unbox in the wrong data type to trigger
// runtime exception.
try
{
long unboxedInt = (long)boxedInt;
}
catch (InvalidCastException ex)
{
Console.WriteLine(ex.Message);
}
At first glance, boxing/unboxing might seem like a rather uneventful language feature that is more
academic than practical. After all, you will seldom need to store a local value type in a local object
variable, as seen here. However, it turns out that the boxing/unboxing process is quite helpful because it
allows you to assume everything can be treated as a System.Object, while the CLR takes care of the
memory-related details on your behalf.
Let’s look at a practical use of these techniques. Assume you have created a nongeneric
System.Collections.ArrayList to hold onto a batch of numeric (stack-allocated) data. If you were to
examine the members of ArrayList, you would find they are prototyped to operate on System.Object
data. Now consider the Add(), Insert(), and Remove() methods, as well as the class indexer:
public class ArrayList : object,
IList, ICollection, IEnumerable, ICloneable
{
...
public virtual int Add(object value);
public virtual void Insert(int index, object value);
public virtual void Remove(object obj);
public virtual object this[int index] {get; set; }
}
ArrayList has been built to operate on objects, which represent data allocated on the heap, so it
might seem strange that the following code compiles and executes without throwing an error:
static void WorkWithArrayList()
{
// Value types are automatically boxed when
// passed to a method requesting an object.
ArrayList myInts = new ArrayList();
myInts.Add(10);
myInts.Add(20);
myInts.Add(35);
}
328