Csharp/C Sharp/Generics/Generic Constraint

Материал из .Net Framework эксперт
Перейти к: навигация, поиск

A base class constraint

<source lang="csharp"> using System; class MyBase {

 public void hello() {
   Console.WriteLine("Hello");
 }

} class B : MyBase { } class C { } class Test<T> where T : MyBase {

 T obj;
 public Test(T o) {
   obj = o;
 }
 public void sayHello() {
   obj.hello();
 }

} class BaseClassConstraintDemo {

 public static void Main() {
   MyBase a = new MyBase();
   B b = new B();
   C c = new C();
   Test<MyBase> t1 = new Test<MyBase>(a);
   t1.sayHello();
   Test t2 = new Test<B>(b);
   t2.sayHello();
   // The following is invalid because
   // C does not inherit MyBase.
   // Test<C> t3 = new Test<C>(c); // Error!
 }

}


      </source>


A new() constructor constraint

<source lang="csharp"> using System; class MyClass {

 public MyClass() {
 }

} class Test<T> where T : new() {

 T obj;
 public Test() {
   // This works because of the new() constraint.
   obj = new T(); // create a T object
 }

} class ConsConstraintDemo {

 public static void Main() {
   Test<MyClass> x = new Test<MyClass>();
 }

}

      </source>


A type parameter can be used as a constraint

<source lang="csharp">

   using System;
   using System.Collections;
   public class Test{
       public static void Main(){
          X<Y, Z> obj=new X<Y, Z>();
       }
   }
   public class Z {
       public void MethodA() {
           Console.WriteLine("Y::MethodA");
       }
   }
   public class Y: Z {
   }
   public class X<T1, T2> where T1:T2 {
       public void MethodB(T1 arg) {
       }
   }
          
      </source>


Combination of Overriding Generic Methods

<source lang="csharp"> /* Base Method Derived Method Comments Nongeneric Generic (open) Permitted Nongeneric Generic (closed) Permitted Generic (open) Nongeneric Not permitted Generic (open) Generic (open) Permitted; must use the same type parameters Generic (open) Generic (closed) Not permitted Generic (closed) Nongeneric Permitted Generic (closed) Generic (closed) Permitted Generic (closed) Generic (open) Not permitted

  • /
</source>


constructor constraint

<source lang="csharp"> using System;

public class Starter {

   public static void Main() {
       MyClass obj = new MyClass();
       obj.MethodA<XClass>();
   }

} public class MyClass {

   public void MethodA<T>()
                where T : XClass, new() {
       Console.WriteLine("MyClass.MethodA");
       T obj = new T();
       obj.MethodB();
   }

} public class XClass {

   public void MethodB() {
       Console.WriteLine("XClass.MethodB");
   }

}

</source>


Default Constructor Constraint

<source lang="csharp">

   using System;
   public class Test{
       public static void Main(){
           Z obj=new Z();
           obj.MethodA<X>();
       }
   }
   public class Z {
       public void MethodA<T>() where T:X, new() {
           Console.WriteLine("Z.MethodA");
           T obj=new T();
           obj.MethodB();
       }
   }
   public class X{
       public void MethodB() {
           Console.WriteLine("X.MethodB");
       }
   }


      </source>


Demonstrate a reference constraint

<source lang="csharp"> using System; class MyClass { } 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;
 }
 public void print(){
    Console.WriteLine(obj);
 }

} class ClassConstraintDemo {

 public static void Main() {
   Test<MyClass> x = new Test<MyClass>();
   // The next line is in error because int is
   // a value type.

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

 }

}

      </source>


Demonstrate a value type constraint

<source lang="csharp"> using System; struct MyStruct { } class MyClass { } class Test<T> where T : struct {

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

} class Test {

 public static void Main() {
   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());

 }

}

      </source>


Derivation Constraint

<source lang="csharp"> using System; public class Starter {

   public static void Main() {
       // good
       MyClass<XClass, YClass> obj = new MyClass<XClass, YClass>();
       // good
       MyClass<XClass, WClass> obj2 = new MyClass<XClass, WClass>();
       // bad
       MyClass<WClass, YClass> obj3 = new MyClass<WClass, YClass>();
   }

} public class MyClass<K, V>

   where K : XClass
   where V : YClass {

} public class XClass { } public class YClass { } public class WClass : YClass { }

</source>


Reference Type Constraint

<source lang="csharp">

   using System;
   using System.Collections;
   public class Test{
       public static void Main(){
           Z<X> obj2=new Z<X>();
       }
   }
   public class Z<T> where T: class {
       public void Iterate(T data) {
       }
   }
   public class X{
   }


      </source>


Reference Type Constraint: A reference type constraint restricts a type parameter to a reference type.

<source lang="csharp"> using System; using System.Collections;

public class Starter {

   public static void Main() {
       // MyClass<int> obj1=new MyClass<int>(); [illegal]
       MyClass<XClass> obj2 = new MyClass<XClass>();
   }

} public class MyClass<T> where T : class {

   public void Iterate(T data) {
   }

} public class XClass { }

</source>


There are five types of constraints:

<source lang="csharp"> /*

   *Derivation constraints state the ascendancy of a type parameter.
   *Interface constraints are interfaces that are implemented by the type parameter.
   *Value type constraints restrict a type parameter to a value type.
   *Reference type constraints restrict a type parameter to a reference type.
   *Constructor constraints stipulate that the type parameter has a default or parameterless constructor.
  • /
</source>


Use an interface constraint

<source lang="csharp"> using System; class NotFoundException : ApplicationException { } public interface IPhoneNumber {

 string Number {
   get;
   set;
 }
 string Name {
   get;
   set;
 }

} class Friend : IPhoneNumber {

 string name;
 string number;
 public Friend(string n, string num) {
   name = n;
   number = num;
 }
 public string Number {
   get { return number; }
   set { number = value; }
 }
 public string Name {
   get { return name; }
   set { name = value; }
 }

} class Supplier : IPhoneNumber {

 string name;
 string number;
 public Supplier(string n, string num) {
   name = n;
   number = num;
 }
 public string Number {
   get { return number; }
   set { number = value; }
 }
 public string Name {
   get { return name; }
   set { name = value; }
 }

} class EmailFriend { } class PhoneList<T> where T : IPhoneNumber {

 T[] phList;
 int end;
 public PhoneList() {
   phList = new T[10];
   end = 0;
 }
 public bool add(T newEntry) {
   if(end == 10) return false;
   phList[end] = newEntry;
   end++;
   return true;
 }
 public T findByName(string name) {
   for(int i=0; i<end; i++) {
     if(phList[i].Name == name)
       return phList[i];
   }
   throw new NotFoundException();
 }
 public T findByNumber(string number) {
   for(int i=0; i<end; i++) {
     if(phList[i].Number == number)
       return phList[i];
   }
   throw new NotFoundException();
 }

} class Test {

 public static void Main() {
   PhoneList<Friend> plist = new PhoneList<Friend>();
   plist.add(new Friend("A", "555-1111"));
   plist.add(new Friend("B", "555-6666"));
   plist.add(new Friend("C", "555-9999"));
   try {
     Friend frnd = plist.findByName("B");
     Console.Write(frnd.Name + ": " + frnd.Number);
   } catch(NotFoundException) {
     Console.WriteLine("Not Found");
   }
   Console.WriteLine();
   PhoneList<Supplier> plist2 = new PhoneList<Supplier>();
   plist2.add(new Supplier("D", "555-4444"));
   plist2.add(new Supplier("E", "555-3333"));
   plist2.add(new Supplier("F", "555-2222"));
   try {
     Supplier sp = plist2.findByNumber("555-2222");
     Console.WriteLine(sp.Name + ": " + sp.Number);
   } catch(NotFoundException) {
       Console.WriteLine("Not Found");
   }
   //PhoneList<EmailFriend> plist3 = new PhoneList<EmailFriend>(); 
 }

}

      </source>