3. Fan type instantiation
Similar to the non-fan type, the compiled fan type also shows the Il command and metadata. Of course, the fan type also encodes the existing and used type parameters.
When constructing a fan type, for example, the instance of stack <int> is Program When constructed, the. net clr jit compiler will convert the Il commands and metadata at a cost. Code In this process, the type parameter will be replaced with the actual type. the same local code will be used for reference to this constructor type later. the process of creating a specific constructor type from the fan type is called the instantiation of the fan type (generic type instantiation ).
. Net runtime will create a specific copy of local code for each paradigm instantiation with a value type, however, instance instantiation with reference types will share a copy of local code (because at the local code level, references are pointers in the same form ).
4. Constraints
If you want to use type parameters to call some methods, what will happen? Public Class Dictionary < K, V >
{
Public Void Add (K key, V value)
{
If (Key. compareto (X) < 0 ) {} // Error, no compareto Method
}
}
Because the key can be defined as any type, the key can only call the method members declared by the object, such as equals,Gethashcode and tostring can, of course, convert the key to a type defined by compareto, for example, icomparable.
Public Class Dictionary < K, V >
{
Public Void Add (K key, V value)
{
If(Icomparable) Key). compareto (X)< 0){}
}
}
Although this solution is available, it will cause runtime check and delay the error to runtime, and throw an invalidcastexception.
To support more compilation checks and reduce the overhead of type conversion, C # allows a list of optional constraints for each type parameter. the definition of constraints is a class table of the where + type parameter + class or interface type [+ constructor constraint new ()].
For the specified dictionary <K, V>, to ensure that the keys implement the icomparable interface, you can constrain K.
Public Class Dictionary < K, V > Where K: icomparable
{
Public Void Add (K key, V value)
{
If(Key. compareto (X)< 0){}
}
}
For a given type parameter, you can specify multiple interfaces as constraints, but you can only specify at most one class as constraints. This is the same as the inherited rule, each type parameter with constraints has a separate WHERE clause. the constructor restricts that the type argument used as a type parameter must have a public-Type constructor without parameters, so that new () can be used () to construct an instance of the specified type.
5. Fan Method
In some cases, the entire class is not required to be a fan type, but only the method member of a class is a fan type. this often happens when a fan type is used as a parameter of a method. for example, if you want to push multiple values in a group to the stack at one time, it is convenient to write a method to implement these values in a method call. for a given construction type, such as stack <int>, this method can be defined as follows:
Void Pushmultiple (Stack < Int > Stack, Params Int [] Values) {
Foreach(IntValueInValues) stack. Push (value );
}
This method can push multiple int values into the stack. however, this method is used for a specific construction type. To enable it to work with the stack <t>, you must define a model method. the model method can include multiple type parameters after the method name. These type parameters can be defined in the parameter list, return type, and method body as follows: Void Pushmultiple < T > (Stack < T > Stack, Params T [] values) {
Foreach(T valueInValues) stack. Push (value );
}
The call method is as follows: Stack < Int > Stack = New Stack < Int > ();
Pushmultiple < Int > (Stack, 1 , 2 , 3 , 4 );
In this way, this method can be reused, but it is inconvenient to specify <int> for each call, which is inconvenient, but in many cases, the compiler can infer the correct parameter type of the method based on the type of other parameters. This process becomes type inferencing. For example, in the previous example, since the first parameter is of the stack <int> type and the following parameter is of the int type, we can infer that the parameter type must be int, so this method can also not specify the type parameter, the call method is as follows: Stack < Int > Stack = New Stack < Int > ();
Pushmultiple (stack, 1 , 2 , 3 , 4 );