Next, we will use the following examples in the previous article:
The so-called generic type means that multiple data types can be operated on the same code by using parameterized types. Generic programming is a programming paradigm that abstracts types by using parameterized types, this allows for more flexible reuse.
When defining generic classes, you can impose restrictions on the types of types that client code can use for type parameters when instantiating classes. If the client code attempts to instantiate a class using a type not allowed by a certain constraint, a compile-time error will occur. These restrictions are called constraints. The constraint is specified using the where context keyword.
The following table lists five types of constraints:
Constraints |
Description |
T: struct |
The type parameter must be a value type. You can specify any value type except nullable. |
T: Class |
The type parameter must be a reference type, including any class, interface, delegate, or array type. |
T: New () |
The type parameter must have a public constructor without parameters. When used with other constraints, the new () constraint must be specified at the end. |
T: <Base Class Name> |
The type parameter must be a specified base class or derived from the specified base class. |
T: <Interface Name> |
The type parameter must be a specified interface or implement the specified interface. Multiple interface constraints can be specified. The constraint interface can also be generic. |
T: u |
The type parameter provided for T must be provided for U or derived from U. This is called the bare type constraint. |
1. derived Constraints
1. Common
Public class myclass5 <t> where T: icomparable {}
2. The constraints are placed after the actual derivation of the class.
Public Class B {}
Public class myclass6 <t>: B where T: icomparable {}
3. It can inherit one base class and multiple interfaces, and the base class is prior to the interface
Public Class B {}
Public class myclass7 <t> where T: B, icomparable, icloneable {} II. constructor Constraints
1. Common
Public class myclass8 <t> where T: New (){}
2. constructor constraints and derived constraints can be combined on the premise that constructor constraints appear at the end of the Constraints List.
Public class myclass8 <t> where T: icomparable, new () {}3. Value Constraints
1. Common
Public class myclass9 <t> where T: struct {}
2. Use with interface constraints at the beginning (cannot be used with base class constraints or constructor constraints)
Public class myclass11 <t> where T: struct, icomparable {} 4. Reference Constraints
1. Common
Public class myclass10 <t> where T: Class {} 5. Multiple generic parameters
Public class myclass12 <t, u> where T: icomparable where u: Class {} 6. Inheritance and generics
Public Class B <t> {}
1. When derived from a generic base class, you can provide type arguments instead of base class generic parameters.
Public class subclass11: B <int>
{}
2. If the subclass is generic, rather than the actual type parameter, you can use the subclass generic parameter as the specified type of the generic base class.
Public class subclass12 <r>: B <r>
{}
3. duplicate the constraint of the base class at the subclass level (when using the generic parameter of the subclass, any constraint specified at the base class level must be repeated at the subclass level)
Public Class B <t> where T: isomeinterface {}
Public class subclass2 <t>: B <t> where T: isomeinterface {}
4. constructor Constraints
Public Class B <t> where T: New ()
{
Public t somemethod ()
{
Return New T ();
}
}
Public class subclass3 <t>: B <t> where T: New () {} 7. generic method (C #2.0 the generic mechanism supports "method naming includes type parameters", which is a generic method)
1. generic methods can be included in both generic and non-generic types.
Public class myclass5
{
Public void mymethod <t> (t ){}
}
2. Declaration and call of generic methods
Public class myclass5
{
Public void mymethod <t> (t ){}
}
Public class app5
{
Public void callmethod ()
{
Myclass5 myclass5 = new myclass5 ();
Myclass5.mymethod <int> (3 );
}
}
3. overload of generic methods
// Reload the first group
Void mymethod1 <t> (T, int I ){}
Void mymethod1 <u> (u, int I ){}
// Reload the second group
Void mymethod2 <t> (int I ){}
Void mymethod2 (int I ){}
// Reload the third group. Assume there are two generic parameters.
Void mymethod3 <t> (t) where T: {}
Void mymethod3 <t> (t) where T: B {}
// Reload group 4
Public class myclass8 <t, u>
{
Public t mymothed (t a, u B)
{
Return;
}
Public t mymothed (u a, t B)
{
Return B;
}
Public int mymothed (int A, int B)
{
Return A + B;
}
}
4. Override of generic methods
(1) Public class mybaseclass1
{
Public Virtual void mymothed <t> (t) where T: New (){}
}
Public class mysubclass1: mybaseclass1
{
Public override void mymothed <t> (t) // No restrictions can be repeated.
{}
}
(2) Public class mybaseclass2
{
Public Virtual void mymothed <t> (T)
{}
}
Public class mysubclass2: mybaseclass2
{
Public override void mymothed <t> (t) // redefine the generic parameter t
{}
} 8. Virtual Methods
Public class baseclass4 <t>
{
Public Virtual t somemethod ()
{
Return default (t );
}
}
Public class subclass4: baseclass4 <int> // The type of the real parameter must be used when the real parameter is used for inheritance.
{
Public override int somemethod ()
{
Return 0;
}
}
Public class subclass5 <t>: baseclass4 <t> // when using generic inheritance, the method is also generic
{
Public override t somemethod ()
{
Return default (t );
}
} 9. The Compiler only allows implicit forced conversion of generic parameters to objects or types specified by constraints.
Class myclass <t> where T: baseclass, isomeinterface
{
Void somemethod (T)
{
Isomeinterface obj1 = T;
Baseclass obj2 = T;
Object obj3 = T;
}
}
Work und: Use a temporary object variable to forcibly convert a generic parameter to any other type
Class myclass2 <t>
{
Void somemethod (T)
{
Object temp = T;
Baseclass OBJ = (baseclass) temp;
}
} 10. The Compiler allows you to forcibly convert a generic parameter to any other interface without converting it to a class.
Class myclass1 <t>
{
Void somemethod (T)
{
Isomeinterface obj1 = (isomeinterface) T;
// Baseclass obj2 = (baseclass) T; // compilation fails.
}
} 11. Use temporary object variables to forcibly convert generic parameters to any other type
Class myclass2 <t>
{
Void somemethod (T)
{
Object temp = T;
Baseclass OBJ = (baseclass) temp;
}
} 12. Use the is and as operators
Public class myclass3 <t>
{
Public void somemethod (T)
{
If (T is int ){}
If (T is already list <int> ){}
String STR = T as string;
If (STR! = NULL ){}
Counter list <int> List = T as counter list <int>;
If (list! = NULL ){}
}
}
Reprinted from: http://www.cnblogs.com/andrew-blog/archive/2012/03/21/ListT_Where.html