C # generic programming

Transfer from --KiddLee

Generic: the operation is implemented in a variety of data types on the same code parameter types. Using a "parameterized type," the abstract type, thereby realizing flexible multiplexing.

Example code:

View Code
 1 class Program
2 {
3 static void Main(string[] args)
4 {
5 int obj = 2;
6 Test<int> test = new Test<int>(obj);
7 Console.WriteLine("int:" + test.obj);
8 string obj2 = "hello world";
9 Test<string> test1 = new Test<string>(obj2);
10 Console.WriteLine("String:" + test1.obj);
11 Console.Read();
12 }
13 }
14
15 class Test<T>
16 {
17 public T obj;
18 public Test(T obj)
19 {
20 this.obj = obj;
21 }
22 }

 

The output is:

int:2

String:hello world

 

Program analysis:

. 1,   the Test is a generic class. T is the paradigm to instantiate type . If T is instantiated as an int, then obj is a member variable of type int, if T is instantiated as string type, then obj is of type string.

2, depending on the type, the above procedure exhibit different values.

 

C # generics mechanisms:

C # CLR generic ability to support at run time: C # generic code when compiling to IL code and metadata, special placeholder to indicate the type of paradigm, and treated with IL-specific instructions support generic operations. The real generic instantiation work with "on-demand" manner, occurs at JIT compile time.

Just look at the code in the Main function of metadata:

View Code
 1 .method private hidebysig static void  Main(string[] args) cil managed
2 {
3 .entrypoint
4 // Code size 79 (0x4f)
5 .maxstack 2
6 .locals init ([0] int32 obj,
7 [1] class CSharpStudy1.Test`1<int32> test,
8 [2] string obj2,
9 [3] class CSharpStudy1.Test`1<string> test1)
10 IL_0000: nop
11 IL_0001: ldc.i4.2
12 IL_0002: stloc.0
13 IL_0003: ldloc.0
14 IL_0004: newobj instance void class CSharpStudy1.Test`1<int32>::.ctor(!0)
15 IL_0009: stloc.1
16 IL_000a: ldstr "int:"
17 IL_000f: ldloc.1
18 IL_0010: ldfld !0 class CSharpStudy1.Test`1<int32>::obj
19 IL_0015: box [mscorlib]System.Int32
20 IL_001a: call string [mscorlib]System.String::Concat(object,
21 object)
22 IL_001f: call void [mscorlib]System.Console::WriteLine(string)
23 IL_0024: nop
24 IL_0025: ldstr "hello world"
25 IL_002a: stloc.2
26 IL_002b: ldloc.2
27 IL_002c: newobj instance void class CSharpStudy1.Test`1<string>::.ctor(!0)
28 IL_0031: stloc.3
29 IL_0032: ldstr "String:"
30 IL_0037: ldloc.3
31 IL_0038: ldfld !0 class CSharpStudy1.Test`1<string>::obj
32 IL_003d: call string [mscorlib]System.String::Concat(string,
33 string)
34 IL_0042: call void [mscorlib]System.Console::WriteLine(string)
35 IL_0047: nop
36 IL_0048: call int32 [mscorlib]System.Console::Read()
37 IL_004d: pop
38 IL_004e: ret
39 } // end of method Program::Main

Look at the metadata Test class constructor:

View Code
 1 .method public hidebysig specialname rtspecialname
2 instance void .ctor(!T obj) cil managed
3 {
4 // Code size 17 (0x11)
5 .maxstack 8
6 IL_0000: ldarg.0
7 IL_0001: call instance void [mscorlib]System.Object::.ctor()
8 IL_0006: nop
9 IL_0007: nop
10 IL_0008: ldarg.0
11 IL_0009: ldarg.1
12 IL_000a: stfld !0 class ConsoleCSharpTest1.Test`1<!T>::obj
13 IL_000f: nop
14 IL_0010: ret
15 } // end of method Test`1::.ctor

Not for generic instantiation, T only acts as a placeholder in the middle of - 1, the first round of compile time, the compiler only Test <T> type have a "generic" version of the IL code and metadata. For example: Test type metadata displayed <T!>

2, when the JIT compiler, when the JIT compiler encounters the first Test <int>, will be instantiated generic type int replace "paradigm Edition" IL code with metadata T--. For example: Main function shown in <int>

3, CLR parameters for all types of "reference type" generic type the same code generated; but if the Type parameter is "value type", for each different "value type", for which the CLR will produce an independent code. Because instantiating a generic type of reference in its allocated memory size is the same, but when instantiating a value type, the size of the allocated memory is not the same.

 

C # Generics features:

1, if the instance of the same generic type parameters, then the JIT editor will reuse this type, so C # generics dynamic ability to avoid the problem of code C ++ static template may result in expanded.

2, carrying the generic type C # rich metadata, so C # generic type technology may be applied to a strong reflection.

3, C # generic use of "base classes, interfaces, constructors, value type / reference type" constraint way to achieve the type of the parameter "Display Constraints", improves the security type, but also the loss of the C ++ template-based " signature "implicit constraint has high flexibility

 

C # generics inheritance:

C # in addition to the generic type declaration (including class structure) alone, but may also comprise generic type declarations in the base class. But if the base class is a generic class, its type or to instantiate or subclass derived from (same generic type) declared parameter 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> // illicit

Providing Type E U, V is a C type, which is derived from the above-said subclass

F type inherits C <string, int>, F think can be seen a non-generic class inherit

G type is illegal, because the G type is not generic, a generic C, G can not provide a generic instantiation C

 

Generic types of members:

Members of the generic type can use type parameters of a generic type declaration. But if there is no type parameter constraints, you can only use public member inherited from System.Object on the type. As shown below:

 

Generic interface:

Generic interface type parameters either instantiated or from type parameters to achieve the class declaration.

 

Generic delegate:

Generic delegate type parameters support the application on the delegate return values ​​and parameters, which can be the same type comes with legal constraints.

View Code
 1 delegate bool MyDelegate<T>(T value);
2 class MyClass
3 {
4 static bool F(int i){...}
5 static bool G(string s){...}
6 static void Main()
7 {
8 MyDelegate<string> p2 = G;
9 MyDelegate<int> p1 = new MyDelegate<int>(F);
10 }
11 }

 

Generic method:

1, C # generics mechanism supports only "type parameters included in the method declaration" - the generic method.

2, C # generic type mechanisms do not support the other members of the parameters declared outside the other methods (including attributes, events, indexers, constructors, destructors), these members themselves may be contained in a generic type, and the use of generic type parameter type.

3, may be included in the generic method of the generic type, it may be included in a non-generic type.

 

Generic method declaration:

1 public static int FunctionName<T>(T value){...}

 

Generic method overload:

1 public void Function1<T>(T a);
2 public void Function1<U>(U a);

Such configuration is not overloaded generic method. Because the compiler can not determine the generic type T and U are different, we can not determine whether these two different methods.

1 public void Function1<T>(int x);
2 public void Function1(int x);

This will constitute a heavy load.

1 public void Function1<T>(T t) where T:A;
2 public void Function1<T>(T t) where T:B;

Such methods can not override a generic configuration. Because the compiler can not determine the constraint conditions A and B are different, we can not determine if the two methods are different.

 

Rewrite generic method:

In the process of rewriting the constraint abstract methods abstract class it is inherited by default.

 1 abstract class Base
2 {
3 public abstract T F<T,U>(T t,U u) where U:T;
4 public abstract T G<T>(T t) where T:IComparable;
5 }
6
7 class MyClass:Base
8 {
9 public override X F<X,Y>(X x,Y y){...}
10 public override T G<T>(T t) where T:IComparable{}
11 }

The method is overwritten two MyClass

F method is legal constraints inherited by default

G is illegal to specify any constraints is redundant

 

Generic constraints:

. 1, C # generic requirements for "all type parameters of the generic type or generic method" of any assumption, have based "explicit constraints", the type of security to maintain the required C #.

2, "explicit constraints" expressed by the where clause, you can specify the "base class constraint", "interface constraints", "constructor constraint", "value type / reference type constraint" were four kinds of constraints.

3, "explicit constraints" not required, if no "explicit constraints" paradigm will only System.Object type parameter type public access methods. For example: In the case began, the definition of member variables that obj. For instance, we added a class Test1 start of that example, we define two public methods Func1, Func2, as shown below in which it:

 

The following began to analyze these constraints:

1. The base class constraints:

View Code
 1 class A
2 {
3 public void Func1(){ }
4 }
5
6 class B
7 {
8 public void Func2(){ }
9 }
10
11 class C<S, T> where S : A where T : B
12 {
13 public C(S s,T t)
14 {
15 //S的变量可以调用Func1方法
16 s.Func1();
17 //T的变量可以调用Func2方法
18 t.Func2();
19 }
20 }

2. interface constraints:

View Code
 1 interface IA<T>
2 {
3 T Func1();
4 }
5
6 interface IB
7 {
8 void Func2();
9 }
10
11 interface IC<T>
12 {
13 T Func3();
14 }
15
16 class MyClass<T, V> where T : IA<T> where V : IB, IC<V>
17 {
18 public MyClass(T t,V v)
19 {
20 //T的对象可以调用Func1
21 t.Func1();
22 //V的对象可以调用Func2和Func3
23 v.Func2();
24 v.Func3();
25 }
26 }

3. constructor constraint:

View Code
 1 class A
2 {
3 public A(){ }
4 }
5
6 class B
7 {
8 public B(int i){ }
9 }
10
11 class C<T> where T : new()
12 {
13 T t;
14 public C()
15 {
16 t = new T();
17 }
18 }
19
20 class D
21 {
22 public void Func()
23 {
24 C<A> c = new C<A>();
25 C<B> d = new C<B>();
26 }
27 }

d objects at compile-time error: of The A type B MUST have have parameterless public constructor in Order to use IT AS Parameter 'T' type or in The Generic Method C <T>

Note: C # now only supports the no-argument constructor constraint

At this time, since we B written a constructor parameter type, so that the system is no longer B automatically create a no-argument constructor, but if we B type was added a constructor with no arguments, the object d to examples of the error will not. B type is defined as follows:

1 class B
2 {
3 public B()
4 { }
5 public B(int i)
6 { }
7 }

Type value / reference types:

1 public struct A { }
2 public class B { }
3
4 public class C<T> where T : struct
5 { }
6
7 C<A> c1 = new C<A>();
8 C<B> c2 = new C<B>();

c2 objects at compile-time error: of The type 'B' MUST BE A non-type Nullable value to use in Order Parameter IT AS 'T' in methor The Generic type or 'C <T>'

to sum up:

1, C # generics capability supported by the CLR at run-time, It is different from C ++ at compile-time static template supported, but also from Java using the "swabbing" simple generic support in the compiler level.

2, C # generics support, including classes, structures, interfaces, delegates, four kinds of generic types, as well as members of the method.

3, C # generic use of "base classes, interfaces, constructors, value type / reference type" constraint way to implement the "explicit constraints" type parameter, it does not support an implicit constraint signature as C ++ template .





 






 









 

 



Reproduced in: https: //my.oschina.net/secyaher/blog/274434

Guess you like

Origin blog.csdn.net/weixin_33711641/article/details/91967115