The benefit of using generics is "code reuse", which greatly improves development efficiency, and generics provide developers with the following benefits:
1, source code protection algorithm sources do not need to be provided to developers using generic algorithms, generic technologies using C + + templates need to be provided. (The current generics technology for C + + templates is less known)
2, type safety to the generic algorithm when specifying the type, the compiler can understand the developer intent, only the compatible type can pass, incompatible when the compile time will be error.
3, clearer code because the compiler enforces type security, reduces the number of transitions that must be made in the source code, making the code easier to maintain and write. For example: DateTime dt=dtlist[0]; values taken from the collection of DateTime can be directly assigned to the DateTime type, without the need for transformation.
4, better performance when manipulating value types, non-generic collections can cause boxing, unboxing, and memory allocations on the managed heap, which can cause frequent garbage collection and impact performance.
1. Generic Infrastructure 1.1 open type and enclosing type
Types with generic type parameters are called open types.
Cannot create an instance. For example, Dictionary<,>, without specifying parameters, it is unclear what this open type is for.
All type arguments are passed with the actual data type as enclosing type.
You cannot restrict a type argument to a type by using a constraint, and you can use a static constructor to guarantee the type. As follows
Internal Sealed class Generictypethatrequiresanenum<t>{ static Generictypethatrequiresanenum () { if (! typeof (T). Isenum) { thrownew ArgumentException ("T must is an enumerated type "); } }}
1.2 Inheritance of generic types
A generic type is still a type, and it can derive from any other type.
Public classNode1<t> { PublicT m_data; PublicNode1<t>M_next; PublicNode1 (T data): This(Data,NULL) { } PublicNode1 (T data, node1<t>next) {m_data=data; M_next=Next; } Public Override stringToString () {//ABC returnM_data. ToString () + ((m_next!=NULL)? M_next. ToString ():NULL); } }
The above example must be used under the same data type, joining the list requires multiple m_data for many types when this structure will not be satisfied, when we can consider extracting a non-generic base class so that the inherited generics can specify multiple types. This is the technique of a generic application.
Public classNode2 {protectedNode2 M_next; PublicNode2 (Node2 next) {M_next=Next; } } Public classTypenode<t>: Node2 { PublicT m_data; PublicTypenode (T data,node2 Next):Base(next) {m_data=data; } PublicTypenode (T data): This(Data,NULL){ } Public Override stringToString () {//Tody is time. returnM_data. ToString () + ((M_next! =NULL) ? M_next. ToString ():NULL); } }1.3 Identity of generic types
This nature does not often use, here simply remember only to understand.
Simplify generics by wrapping a layer of "<" ">" in a multi-package.
Class datetimelist:list<datetime>{
There is no need to put any code here.
}
There is no <,> symbol for this use.
Datetimelist dt=new datetimelist ();
This is just a superficial convenience, and you should never define a new class simply for the purpose of enhancing the readability of the code, in fact it will not, but it would lose identity and equality, the following code is flase
Boolean sametype= (typeof (List<datetime>) ==typeof (datetimelist));
You can use the using directive to compensate for equality by adding the following result as true;
Using datetimelist=system.collections.generic.list<system.datetime>;
1.4 Code Explosion
A method that uses a generic type parameter at JIT (compile-time) compilation, the CLR gets the Il of the method, replaces it with the specified arguments, creates the appropriate local code, and the disadvantage is that the CLR is going to generate local code for each of the different methods, types of combinations, which can cause the application set to grow significantly, corrupting performance, called Code exploded.
However, some optimizations have been built into the CRL to mitigate the code explosion. When all assemblies use list<datetime>, they are generated only once, believing that all reference type arguments are exactly the same,list<string> and list<stream> can be public, Because all reference-type arguments or variables are actually pointers to objects on the heap, and pointers are all manipulated in the same way.
2, generic interface
An example of a generic interface is the IComparable interface, which is written in detail in the interface
3, generic delegate
It is recommended to use the generic action and Func delegates, which will be described in a later delegate
4, inverse and covariant generic type arguments for delegates and interfaces
Invariants (invariant) indicate that a generic type is immutable.
The inverse variable (contravariant) indicates that a generic type parameter can be changed from a base class to a derived class of that class, marked with an in keyword, and appears only at the input location.
A covariant variable (covariant) indicates that a generic type can be changed from one derived class to its base type, marked with the Out keyword, and appears only in the output location.
Public delegate TResult Func<in t,out tresult> (T Arg);
Func<object,argumentexception> Fn1=null;
Func<string,exception> fn2=fn1;//no need to show conversions here, because the inverse variable, the covariance
Call the delegate exception E=fn2 ("");
When using a delegate to get generic parameters and return values, it is recommended to use the in and out keywords as much as possible, as there is no adverse reaction.
Generic interfaces, like generic delegates, can also be used out and in.
5, generic method
With an example of the definition of a generic type, the following type defines a type parameter, and a method defines its own private type parameter.
class Generictype<t>{ private T m_value; Public GenericType (T value) {m_value=value;} Public TOutput Coverter (TOutput) () { TOutput result= (TOutput) convert.changetype (M_value, typeof(TOutput)); return result; } }
Here is a comparison of the classic common method, 2 parameters Interchange
Private Static void Swap<t> (ref T O1,ref T O2) { T temp=O1; O1=O2; O2=temp; }
6 generic constraints
Make sure that you use the current generic type that you want.
For example, the following method will give an error when the type does not provide a CompareTo method.
private static T min<t> (t O1,to2) {
if (O1.compareto (O2) <0)
return O1;
return O2;
}
At this point we need to add a generic constraint to the generic method.
private static T min<t> (t O1,to2) where t:icomparable<t>{
if (O1.compareto (O2) <0)
return O1;
return O2;
}
Generic constraints are divided into 3 main types.
1, the main constraint can be a reference type, the argument must be the same as or derived from the constraint,
For example , where T:stream, using the generic method must be a Stream type or its derived type.
where T:class, using the generic method must be a reference type.
2, secondary constraint a secondary constraint represents an excuse type, and the specified parameter must implement all interface constraints such as where T:icomparable<t>
3, the constructor constraint specifies that the argument must implement a non-abstract type of public parameterless constructor where T:new ()
The following is a generic method used in the project, and the template is deserialized. Using the Newtonsoft.json
PublicT gettemplatedata<t> ()whereT:templatedata {if(!string. IsNullOrEmpty (TEMPLATEDATAJSONSTR)) {T obj= (T) jsonconvert.deserializeobject (TEMPLATEDATAJSONSTR,typeof(T)); Obj. CheckField (); returnobj; } Else return NULL; } Public voidSettemplatedata (TemplateData templatedata) {templatedatajsonstr=Jsonconvert.serializeobject (TemplateData); }
"Clr in C #" generics