站内搜索: 请输入搜索关键词
当前页面: 图书首页 > NET For Java Developers Migrating To C#

NET For Java Developers Migrating To C#

[ directory ] Previous Section Next Section

7.6 Boxing and Unboxing

In 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 Boxing

Boxing 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 Unboxing

Unboxing 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:

  1. Checking the object instance to make sure it is a boxed value of the given value type

  2. Copying the value from the instance into the value-type variable

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 Operator

Operators 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 ] Previous Section Next Section