Subscribe

RSS Feed (xml)

Reference Type and Value Type Constraints

The last two constraints which explained in the previous posts enable you to indicate that a type argument must be either a reference type or a value type. These constraints are useful in the few cases where the difference between reference and value types is important to generic code. The general forms of the where statements for these constraints are shown here:

where T : class

where T : struct

Here, T is the name of the type parameter. When additional constraints are present, class or struct must be the first constraint in the list.

Here is an example that demonstrates the reference type constraint:

// Demonstrate a reference constraint.

using System;
class MyClass {
  //...
}

// Use a reference constraint.
class Test<T> where T : class {
  T obj;

  public Test() {
    // The following statement is legal only
    // because T is guaranteed to be a reference
    // type, which can be assigned the value null.
    obj = null;
  }

  // ...
}

class ClassConstraintDemo {
  public static void Main() {

    // The following is OK because MyClass is a class.
    Test<MyClass> x = new Test<MyClass>();

    // The next line is in error because int is
    // a value type.
//    Test<int> y = new Test<int>();
  }
}

First, notice how Test is declared:

class Test<T> where T : class {

The class constraint requires that any type argument for T be a reference type. In this program, this is necessary because of what occurs inside the Test constructor:

public Test() {
  // The following statement is legal only
  // because T is guaranteed to be a reference
  // type, which can be assigned the value null.
  obj = null;
}

Here, obj (which is of type T) is assigned the value null. This assignment is valid only for reference types. In C#, you cannot assign null to a value type. Therefore, without the constraint, the assignment would not have been valid, and the compile would have failed. This is one case in which the difference between value types and reference types might be important to a generic routine.

The value type constraint is the complement of the reference type constraint. It simply ensures that any type argument is a value type, including a struct or an enum. Here is an example:

// Demonstrate a value type constraint.

using System;

struct MyStruct {
  //...
}

class MyClass {
  // ...
}

class Test<T> where T : struct {
  T obj;

  public Test(T x) {
    obj = x;
  }

  // ...
}

class ValueConstraintDemo {
  public static void Main() {

    // Both of these declarations are legal.

    Test<MyStruct> x = new Test<MyStruct>(new MyStruct());

    Test<int> y = new Test<int>(10);

    // But, the following declaration is illegal!
//    Test<MyClass> z = new Test<MyClass>(new MyClass());
  }
}

In this program, Test is declared as shown here:

class Test<T> where T : struct {

Because T of Test now has the struct constraint, T can be passed only value type arguments. This means that Test<MyStruct> and Test<int> are valid, but Test<MyClass> is not. To prove this, try removing the comment symbol from the start of the last line in the program and recompiling. An error will be reported.

Technorati :

No comments:

Post a Comment

Archives

LocalsAdda.com-Variety In Web World

Fun Mail - Fun in the Mail