boxing and unboxing
In Chapter 2, “Core C#,” you learned that all types, both the simple predefined types such as int and char,and the complex types such as classes and structs, derive from the object type. This means that you cantreat even literal values as though they are objects:
string s = 10.ToString();
However, you also saw that C# data types are divided into value types, which are allocated on the stack,and reference types, which are allocated on the heap. How does this square with the ability to call methodson an int, if the int is nothing more than a 4-byte value on the stack?
The way C# achieves this is through a bit of magic called boxing. Boxing and its counterpart, unboxing,allow you to convert value types to reference types and then back to value types. We include this in thesection on casting because this is essentially what you are doing — you are casting your value to the objecttype. Boxing is the term used to describe the transformation of a value type to a reference type. Basically,the runtime creates a temporary reference-type box for the object on the heap.
This conversion can occur implicitly, as in the preceding example, but you can also perform it explicitly:
int myIntNumber = 20;
object myObject = myIntNumber;
Unboxing is the term used to describe the reverse process, where the value of a previously boxed value typeis cast back to a value type. We use the term cast here, because this has to be done explicitly. The syntax issimilar to explicit type conversions already described:
int myIntNumber = 20;
object myObject = myIntNumber; // Box the int
int mySecondNumber = (int)myObject; // Unbox it back into an int
You can only unbox a variable that has previously been boxed. If you execute the last line when myObject isnot a boxed int, you will get an exception thrown at runtime.
One word of warning: when unboxing, you have to be careful that the receiving value variable has enoughroom to store all the bytes in the value being unboxed. C#’s ints, for example, are only 32 bits long, sounboxing a long value (64 bits) into an int as shown here will result in an InvalidCastException:
long myLongNumber = 333333423;
object myObject = (object)myLongNumber;int myIntNumber = (int)myObject;