Free mag vol1 | Page 388

CHAPTER 9  COLLECTIONS AND GENERICS } Boxing can be formally defined as the process of explicitly assigning a value type to a System.Object variable. When you box a value, the CLR allocates a new object on the heap and copies the value type’s value (25, in this case) into that instance. What is returned to you is a reference to the newly allocated heap-based object. The opposite operation is also permitted through unboxing. Unboxing is the process of converting the value held in the object reference back into a corresponding value type on the stack. Syntactically speaking, an unboxing operation looks like a normal casting operation. However, the semantics are quite different. The CLR begins by verifying that the receiving data type is equivalent to the boxed type; and if so, it copies the value back into a local stack-based variable. For example, the following unboxing operations work successfully, given that the underlying type of the boxedInt is indeed an int: static void SimpleBoxUnboxOperation() { // Make a ValueType (int) variable. int myInt = 25; // Box the int into an object reference. object boxedInt = myInt; } // Unbox the reference back into a corresponding int. int unboxedInt = (int)boxedInt; When the C# compiler encounters boxing/unboxing syntax, it emits CIL code that contains the box/unbox op codes. If you were to examine your compiled assembly using ildasm.exe, you would find the following: .method private hidebysig static void SimpleBoxUnboxOperation() cil managed { // Code size 19 (0x13) .maxstack 1 .locals init ([0] int32 myInt, [1] object boxedInt, [2] int32 unboxedInt) IL_0000: nop IL_0001: ldc.i4.s 25 IL_0003: stloc.0 IL_0004: ldloc.0 IL_0005: box [mscorlib]System.Int32 IL_000a: stloc.1 IL_000b: ldloc.1 IL_000c: unbox.any [mscorlib]System.Int32 IL_0011: stloc.2 IL_0012: ret } // end of method Program::SimpleBoxUnboxOperation Remember that unlike when performing a typical cast, you must unbox into an appropriate data type. If you attempt to unbox a piece of data into the incorrect data type, an InvalidCastException exception will be thrown. To be perfectly safe, you should wrap each unboxing operation in try/catch logic; however, this would be quite labor intensive to do for every unboxing operation. Consider the following code update, which will throw an error because you’re attempting to unbox the boxed int into a long: 327 b