| [ directory ] |
|
7.6 Boxing and UnboxingIn the Java programming language, primitives and objects are not interchangeable. Although there are methods to convert a primitive to its wrapper object and vice versa, you cannot pass a primitive to a method whose signature expects the wrapper object and vice versa. For example, in the following method call, the age parameter literal must be an int primitive; similarly, the result of this method must be assigned to the wrapper object for int, which is java.lang.Integer. public Integer setAge(int age); C# addresses this problem via boxing and unboxing, wherein the alias of the value type is interchangeable with its System namespace class. Boxing and unboxing enable value types to be treated as objects. 7.6.1 BoxingBoxing is an implicit conversion of a value type to the type object or to any interface type implemented by this value type. Boxing the value of a value type allocates an object instance and copies the value into the new object. Consider the following declaration of a value-type variable: int i = 123; The following statement implicitly applies the boxing operation on the variable i: object o = i; This statement creates a reference to an object o (on the stack) that references a value of the type int (on the heap). This value is a copy of the value-type value assigned to the variable i. It is also possible, but not necessary, to perform the boxing explicitly, as in the following example: int i = 123; object o = (object) i; Boxing allows you to pass primitives as parameters to the methods of the System.Collections class (see Chapter 14). Listing 7.5 shows how boxing allows you to pass value-type arguments to the classes of the System.Collections namespace. Listing 7.5 Boxing Test (C#)
using System;
using System.Collections;
class BoxingTest {
public static void Main() {
ArrayList list = new ArrayList();
for (int i = 0; i < 10; ++i) list.Add(i);
for (int i = 0; i < 10; ++i) {
Console.Write(" "+list[i]);
}
}
}
Here is the output of Listing 7.5: 0 1 2 3 4 5 6 7 8 9 The runtime automatically converts the value type i to its equivalent System.Int32 and adds it to ArrayList. 7.6.2 UnboxingUnboxing is an explicit conversion from the type object to a value type or from an interface type to a value type that implements the interface. An unboxing operation consists of two actions:
The following statements demonstrate both boxing and unboxing operations: int i = 123; // A value type object box = i; // Boxing int j = (int)box; // Unboxing For an unboxing conversion to a given value type to succeed at runtime, the value of the source argument must be a reference to an object that was previously created by boxing a value of that value type. If the source argument is null or is a reference to an incompatible object, an InvalidCast Exception is thrown. Listing 7.6 illustrates invalid unboxing. Listing 7.6 Invalid Unboxing (C#)
using System;
public class UnboxingTest {
public static void Main() {
int i = 123;
// Boxing
object o = i;
// Reference to incompatible object produces
InvalidCastException
try {
int j = (short) o;
Console.WriteLine("Unboxing OK.");
}
catch (InvalidCastException e) {
Console.WriteLine(e.Message);
}
}
}
The output of Listing 7.6 is as follows: Specified cast is not valid. 7.6.3 The typeof OperatorOperators are discussed in Chapter 8, but we introduce the typeof operator here because it deals with data types. The typeof operator is used to obtain the System.Type object for a type. To obtain the runtime type of an expression, you can use the .NET Framework method GetType. A close equivalent of the typeof operator in Java is the class operator. For example, in Java you typically write the following: String name = MyClass.class.getName(); Here, MyClass.class gives a reference to the java.lang.Class object. Similarly, the typeof operator gives a reference to a System.Type object, as illustrated in Listing 7.7. Listing 7.7 Using the typeof Operator (C#)
using System;
public class TypeOfTest {
public static void Main() {
Type t = typeof(TypeOfTest);
Console.WriteLine("The type of this class is "+t);
TypeOfTest tObj = new TypeOfTest();
Console.WriteLine("The type of this class is
"+tObj.GetType());
}
}
The output of Listing 7.7 is as follows: The type of this class is TypeOfTest The type of this class is TypeOfTest Notice that the typeof operator works on the literal name of the type, whereas the GetType method must be applied to an instantiated object of the type. To understand the pointer data type, you need to first understand unsafe code in C#. That's what we discuss next. |
| [ directory ] |
|