Generics: The use of parameterized types to implement multiple data types on the same piece of code. Use the parameterized type to abstract the type for flexible reuse.
Example code:
Class Program
{
static void Main (string[] args)
{
int obj = 2;
test<int> test = new test<int> (obj);
Console.WriteLine ("Int:" + test.obj);
String obj2 = "Hello World";
test<string> test1 = new test<string> (OBJ2);
Console.WriteLine ("String:" + test1.obj);
Console.read ();
}
}
Class test<t>
{
public T obj;
Public Test (T obj)
{
This.obj = obj;
}
}
The output is:
Int:2
String:hello World
Program Analysis:
1, Test is a generic class. T is the type of paradigm to instantiate. if T is instantiated as an int, then the member variable, obj, is of type int, and if T is instantiated as a string, then obj is the string type.
2, according to different types, the above program shows a different value.
C # generic mechanism:
C # generics have the CLR support at runtime: C # generic code, when compiled into IL code and metadata, uses special placeholders to represent the pattern type and supports generic operations with proprietary IL directives. And the true generics instantiation works in a "On-demand" way, at JIT compile time.
Look at the metadata for the main function in the code just now.
. method private Hidebysig static void Main (string[] args) cil managed
{
. entrypoint
Code size (0x4f)
. maxstack 2
. Locals init ([0] int32 obj,
[1] class csharpstudy1.test ' 1<int32> Test,
[2] String obj2,
[3] class Csharpstudy1.test ' 1<string> test1)
Il_0000:nop
il_0001:ldc.i4.2
il_0002:stloc.0
il_0003:ldloc.0
Il_0004:newobj instance void class Csharpstudy1.test ' 1<int32>::.ctor (!0)
Il_0009:stloc.1
Il_000a:ldstr "int:"
Il_000f:ldloc.1
IL_0010:LDFLD!0 class Csharpstudy1.test ' 1<int32>::obj
Il_0015:box [Mscorlib]system.int32
Il_001a:call string [Mscorlib]system.string::concat (object,
Object
Il_001f:call void [Mscorlib]system.console::writeline (String)
Il_0024:nop
Il_0025:ldstr "Hello World"
Il_002a:stloc.2
Il_002b:ldloc.2
Il_002c:newobj instance void class Csharpstudy1.test ' 1<string>::.ctor (!0)
Il_0031:stloc.3
Il_0032:ldstr "String:"
Il_0037:ldloc.3
IL_0038:LDFLD!0 class Csharpstudy1.test ' 1<string>::obj
Il_003d:call string [Mscorlib]system.string::concat (String,
String
Il_0042:call void [Mscorlib]system.console::writeline (String)
Il_0047:nop
Il_0048:call int32 [Mscorlib]system.console::read ()
Il_004d:pop
Il_004e:ret
}//End of method Program::main
Look again at the metadata of the constructor in the test class
. method public Hidebysig specialname rtspecialname
instance void. ctor (! T-obj) cil managed
{
Code size (0x11)
. maxstack 8
il_0000:ldarg.0
Il_0001:call instance void [Mscorlib]system.object::.ctor ()
Il_0006:nop
Il_0007:nop
il_0008:ldarg.0
Il_0009:ldarg.1
IL_000A:STFLD!0 class Consolecsharptest1.test ' 1<! T>::obj
Il_000f:nop
Il_0010:ret
}//End of method Test ' 1::.ctor
1. At the first round of compilation, the compiler only produces "generic" IL Code and metadata for the test<t> type--not a generic instantiation, and T only acts as a placeholder in the middle. Example: <! displayed in the test type metadata T>
2. At JIT compile time, when the JIT compiler encounters test<int> for the first time, it will replace the "paradigm" il code with int with the t--of the metadata in the instantiation of the generic type. For example: The <int> displayed in the main function
3. The CLR produces the same code for all generic types whose type arguments are reference types, but if the type parameter is a value type, for each of the different value types, the CLR generates a separate piece of code for it. Because instantiating a generic of a reference type, it allocates the same size in memory, but when a value type is instantiated, the size allocated in memory is not the same.
C # Generic Features:
1. If the parameters of the instantiated generic type are the same, the JIT editor reuses the type, so the dynamic generic capability of C # avoids the problem of code bloat that could be caused by C + + static templates.
2. C # Generic types carry rich metadata, so C # generic types can be applied to powerful reflection techniques.
3. C # Generics Adopt "base class, interface, constructor, value type/reference type" to implement "display constraint" of type parameter, improve type safety, and lose the high flexibility of C + + template implicit constraint based on "signature".
C # Generic inheritance:
In addition to declaring generic types (including classes and structs) separately, C # can also include declarations of generic types in the base class. But if the base class is a generic class, its type is either instantiated or derived from a type parameter declared by a subclass (also a generic type), see the following types
Class c<u,v>
Class d:c<string,int>
Class e<u,v>:c<u,v>
Class f<u,v>:c<string,int>
Class G:c<u,v>//illegal
Type E provides u, V for Type C, which is what it says is derived from subclasses
The F-type inherits from the C<string,int>, and the individual thinks it can be regarded as f inheriting a non-generic class
The G type is illegal because the G type is not generic, C is generic, and g cannot provide generic instantiation of C
Members of generic types:
A member of a generic type can use a type parameter in a generic type declaration. However, if there is no constraint on the type parameter, only the public member inherited from System.Object can be used on that type. Such as:
Generic interface:
The type parameter of a generic interface is either instantiated or derived from the type parameter that implements the class declaration
Generic delegate:
Generic delegates support the application of parameter types on delegate return values and parameters, which can also be accompanied by legitimate constraints
delegate bool Mydelegate<t> (T value);
Class MyClass
{
static bool F (int i) {...}
static bool G (string s) {...}
static void Main ()
{
mydelegate<string> P2 = G;
mydelegate<int> P1 = new mydelegate<int> (F);
}
}
Generic methods:
1. The C # generic mechanism only supports "include type parameters on method declarations"-that is, generic methods.
2. The C # Generic mechanism does not support the inclusion of type parameters on declarations other than methods, including properties, events, indexers, constructors, and destructors, but the members themselves can be included in the generic type and use the type parameters of the generic type.
3. Generic methods can be included either in a generic type or in a non-generic type.
Generic method declaration: The following
public static int functionname<t> (T value) {...}
Overloads of generic methods:
public void function1<t> (T a);
public void function1<u> (U a);
This is an overload that cannot form a generic method. Because the compiler cannot determine whether the generic type T and U are different, it is not possible to determine whether the two methods are different
public void function1<t> (int x);
public void Function1 (int x);
This can form an overloaded
public void function1<t> (T t) where t:a;
public void function1<t> (T t) where t:b;
This does not constitute an overload of the generic method. Because the compiler cannot determine whether a and B in a constraint are different, it is not possible to determine whether the two methods are different
Generic method Overrides:
In the process of rewriting, the constraints of abstract methods in abstract classes are inherited by default. As follows:
Abstract class Base
{
Public abstract T f<t,u> (T t,u U) where u:t;
Public abstract T g<t> (T T) where t:icomparable;
}
Class Myclass:base
{
public override x F<x,y> (x × y y) {...}
public override T G<t> (T T) where t:icomparable{}
}
For the two overridden methods in MyClass
The F method is legal, and the constraint is inherited by default
The G method is illegal and specifies that any constraints are superfluous
Generic constraints:
1. C # generics require any assumption of "type parameters for all generic types or generic methods" based on "explicit constraints" to maintain type safety required by C #.
2, "explicit constraint" is expressed by a WHERE clause, you can specify "base class Constraints", "Interface Constraints", "constructor Constraints", "Value type/reference type constraints" a total of four constraints.
3, "explicit constraint" is not required, if you do not specify an explicit constraint, the generic type parameter will only access the public method in the System.Object type. For example: In the first example, the definition of the OBJ member variable. For example, we add a Test1 class to the first example, in which we define two public methods Func1, FUNC2, such as:
Here we begin to analyze these constraints:
Base class Constraints:
Class A
{
public void Func1 ()
{ }
}
Class B
{
public void Func2 ()
{ }
}
Class C<s, t>
where s:a
where t:b
{
Public C (S s,t T)
{
s variable can call the Func1 method
S.func1 ();
The variable of T can call the Func2 method
T.FUNC2 ();
}
}
Interface constraints:
Interface ia<t>
{
T Func1 ();
}
Interface IB
{
void Func2 ();
}
Interface ic<t>
{
T Func3 ();
}
Class Myclass<t, v>
where t:ia<t>
where V:ib, ic<v>
{
Public MyClass (T t,v V)
{
The object of T can call FUNC1
T.func1 ();
The objects of V can call FUNC2 and Func3
V.FUNC2 ();
V.func3 ();
}
}
Constructor constraints:
Class A
{
Public A ()
{ }
}
Class B
{
Public B (int i)
{ }
}
Class c<t> where T:new ()
{
T T;
Public C ()
{
t = new T ();
}
}
Class D
{
public void Func ()
{
c<a> C = new c<a> ();
C<b> d = new c<b> ();
}
}
D object in compile times error: The type B must has a public parameterless constructor in order to use it as parameter ' T ' in the generic type or method c<t>
Note: C # now supports only argument-free constructor constraints
Because we write a parametric constructor for type B, the system no longer automatically creates a parameterless constructor for B, but if we add a parameterless constructor to type B, then the instantiation of object D will not cause an error. Type B is defined as follows:
Class B
{
Public B ()
{ }
Public B (int i)
{ }
}
Value type/reference type:
public struct A {}
public class B {}
public class c<t> where t:struct
{
}
c<a> C1 = new c<a> ();
c<b> C2 = new c<b> ();
C2 object in compile times error: The type ' B ' must is a non-nullable value type in order to use it as parameter ' T ' in the generic type or Metho R ' c<t> '
Summarize:
1. The generic capabilities of C # are supported by the CLR at run time, which differs from the static templates that C + + supports at compile time, as well as the simple generics supported by Java at the compiler level using the Wipe method.
2. Generic support for C # includes classes, structs, interfaces, delegates four generic types, and method members.
3. C # Generics use the "base class, interface, constructor, value type/reference type" constraint to implement an "explicit constraint" on the type parameter, which does not support signature-based implicit constraints such as C + + templates.
Reprinted from: http://www.cnblogs.com/kid-li/archive/2006/11/29/577045.html
C # Generic Programming