Preface: The previous two chapters introduce the two common techniques of C #: C # Basic Series-Reflection Notes and C # Basic series--attribute features. This chapter summarizes the use of C # generic technologies. According to the experience of bloggers, the generics are also used for reuse, and most of the time they are combined with reflection. This time, we are going to talk about WWH (what, why, how).
1. What is generics: use parameterized types to implement multiple data types on the same code. Use the parameterized type to abstract the type for flexible reuse. How to understand, in fact, according to the blogger's understanding, generics are to abstract the type, using abstract types or objects to implement certain functions and business, and then all need to use these functions and the specific type of business to invoke the generic methods and delegates. Hehe, is not still a bit dizzy, don't worry, we come to an example:
Let's start by defining a scenario where we use the SQL statement to query the default resulting in weakly typed DataTable, DataReader, and so on, and we need to use the Lamada expression for some complex calculations on the query to the result set. You need to convert the DataTable to the corresponding List<t> collection, first to define a generic method:
Public StaticList<t> getlistbydatetable<t>(DataTable dt) {List<T> modellist =NewList<t>(); Try { //1. If the DataTable does not have data, return directly if(dt = =NULL|| Dt. Rows.Count = =0) { returnmodellist; } //2. Traversing a DataTable fill entity varLstcol =dt. Columns; foreach(DataRow Drinchdt. Rows) {T model=default(T); //if it is an object (this is typically used in situations where an entity class cannot be represented), then the JSON is then deserialized to object if(typeof(T). Equals (typeof(Object))) { varStrjson ="{"; foreach(DataColumn OcolinchLstcol) { varOattrvalue = Convert.isdbnull (Dr[ocol.columnname])?NULL: Dr[ocol.columnname]; Strjson+="\""+ Ocol.columnname +"\":\""+ Oattrvalue +"\","; } Strjson= Strjson.tostring (). Trim (',') +"}"; Model= e2eres.javascriptstrtoobj<t>(Strjson); } Else{model= fillentitybydt<t>(DT, DR); } modellist.add (model); } } Catch { } returnmodellist; } //populating an entity class with a DataTable Private StaticT fillentitybydt<t>(DataTable dt, DataRow DR) {T model= (T)typeof(T). GetConstructor (NewSystem.type[] {}). Invoke (New Object[] { });//reflection gets the entity of the generic classpropertyinfo[] Pro =typeof(T). GetProperties (BindingFlags.Instance |bindingflags.public); Type type=model. GetType (); foreach(PropertyInfo PropertyInfoinchPro) { if(dt. Columns.contains (Propertyinfo.name)) {if(Convert.isdbnull (Dr[propertyinfo.name])) {Continue; } if(!string. IsNullOrEmpty (Convert.ToString (Dr[propertyinfo.name]))) {type. GetProperty (Propertyinfo.name). SetValue (model, Dr[propertyinfo.name],NULL); } } } returnmodel; }
With this generic approach, we are not a good reuse when converting DataTable and concrete list<model>.
2, why the use of generics: Bo Master remembers the first two years of work to have an interview when asked, "What are the advantages of generics?" , then how to answer not remember, only know that the interview is not very smooth ~ ~ Why to use generics it? Bloggers feel that the main advantages of generics are the following points:
(1) Guarantee the type of security: Generics constrain the type of the variable, ensuring the type of security. such as List<int> and ArrayList. The List<int> collection can only add variables of type int, ArrayList can add any common type and compile without prompting for errors.
(2) Avoid unnecessary packing, unpacking operation, improve the performance of the program: generic variable fixed type, when used to know whether the value type or reference type, avoid unnecessary boxing, unpacking operations. To illustrate:
Before using generics, we use object instead.
Object a=1; // because it is of type object, boxing is done automatically. int b= (int) A; // cast, unboxing operation. Such a go, when the number of times will affect the operation of the program efficiency.
After using generics
Public Static T getvalue<t>(t a) { return A;} Public Static void Main () { int b=getvalue<int> (1);//When using this method, you have specified that the type is int, So there will be no boxing and unpacking operations. }
(3) Improve the reuse of methods and algorithms. The above example basically illustrates this advantage.
3, the use of generics:
(1) Use of generic methods: This is also one of the most used uses of bloggers, such as this generic method is generally a static general method, such as the original project used in the conversion of the DataGridViewRow object to the corresponding entity model is as follows:
Public StaticT toobject<t> (DataGridViewRow Item)whereT:class { varModel = Item. Databounditem asT; if(Model! =NULL) returnmodel; varDr = Item. Databounditem asSystem.Data.DataRowView; Model= (T)typeof(T). GetConstructor (NewSystem.type[] {}). Invoke (New Object[] { });//reflection gets the entity of the generic classpropertyinfo[] Pro =typeof(T). GetProperties (BindingFlags.Instance |bindingflags.public); Type type=model. GetType (); foreach(PropertyInfo PropertyInfoinchPro) { if(Convert.isdbnull (Dr[propertyinfo.name])) {Continue; } if(!string. IsNullOrEmpty (convert.tostring (Dr[propertyinfo.name ))) {varPropertyType =Propertyinfo.propertytype; if(PropertyType = =typeof(system.nullable<datetime>) | | PropertyType = =typeof(DateTime)) {type. GetProperty (Propertyinfo.name). SetValue (model, Convert.todatetime (Dr[propertyinfo.name]),NULL); } Else if(PropertyType = =typeof(system.nullable<decimal>) | | PropertyType = =typeof(decimal) ) {type. GetProperty (Propertyinfo.name). SetValue (model, Convert.todecimal (Dr[propertyinfo.name]),NULL); } Else if(PropertyType = =typeof(system.nullable<int>) | | PropertyType = =typeof(int) ) {type. GetProperty (Propertyinfo.name). SetValue (model, Convert.ToInt32 (Dr[propertyinfo.name]),NULL); } Else if(PropertyType = =typeof(system.nullable<Double>) | | PropertyType = =typeof(Double) ) {type. GetProperty (Propertyinfo.name). SetValue (model, convert.todouble (Dr[propertyinfo.name]),NULL); } Else{type. GetProperty (Propertyinfo.name). SetValue (model, Dr[propertyinfo.name],NULL); } } } returnmodel; }
Considerations for using generic methods:
- Overloading of generic methods: public void fun1<t> (T a), and public void fun1<u> (U a); is not overloaded, this is actually very good to understand, because T and U are actually a representative symbol of the generic type;
- Overriding of the generic method: The following method overrides the Funca rewrite is correct, and the FUNCB rewrite is incorrect because the constraint is inherited by default, and no further writing is necessary.
Abstract classbaseclass{ Public AbstractT funca<t,u> (t t,u U)whereu:t; Public AbstractT funcb<t> (T T)wheret:icomparable;} classclassa:baseclass{ Public OverrideX funca<x,y>(X × y y) {...} Public OverrideT funcb<t> (T T)whereT:icomparable{...}}
(2) Use of generic classes:
Public class Class_base<dto, t>{}
You must specify two generic classes when using this class.
(3) Use of generic interfaces and generic inheritance:
The type parameter of a generic interface is either instantiated or derived from the type parameter that implements the class declaration
Public Interface Interface_base<t>{}publicclass class_base<dto, t>: interface_base<dto >{}
DTOs originate from implementation class Class_base
(4) The use of generic delegate: In fact, this usage of bloggers really use very little, but the original has seen Daniel similar code.
To define a generic delegate:
Public Delegate void mydelegate<t> (T obj);
Use of generic delegates:
Public Delegate void Mydelegate<t>(T obj); Static void Main (string[] args) { varnew mydelegate<int>( Printint); Method (1); Console.readkey ();} Static void printint (int i) { Console.WriteLine (i);}
(5) Generic constraint: Used to constrain the characteristics of a generic type. There are a few common types of generic constraints:
Formatting of generic constraints
Public class Imps_base<dto, t>: ifs_base<dto> where t:baseentity whereclass {}
| Constraints |
Description |
T:struct |
The type parameter must be a value type. You can specify any value type other than 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 with no parameters. When used with other constraints, the new () constraint must be specified last. |
t:< base class name > |
The type parameter must be the specified base class or derive from the specified base class. |
t:< Interface Name > |
The type parameter must be the specified interface or implement the specified interface. You can specify multiple interface constraints. The constraint interface can also be generic. |
T:u |
The type parameter provided for T must be either a parameter supplied for u or a parameter derived from U. This is called a bare type constraint. |
C # Basic Series--small-talk generics