1. What is a generic type?
Generics are classes, structs, interfaces, and methods that have placeholders (type parameters), which are placeholders for one or more types that are stored or used by classes, structs, interfaces, and methods. A generic collection class can use a type parameter as a placeholder for the type of object it stores, and the type parameter appears as the type of its field and the parameter type of its method. A generic method can use its type parameter as the type of its return value or as a type of one of its parameters.
Generics defer the determination of the type of a class or method until the class or method is instantiated, that is, the first declaration is to not specify a type, wait until you want to use (instantiate) to specify the type, and generics can be used for classes, methods, delegates, events, and so on.
? Example
public class Sorthelper<t> {static void Main (string[] args) {sorthelper<int> so RT =new sorthelper<int> (); Add the appropriate type to the <> define T as a type parameter//generics defer the determination of the type of the class or method until the class or method is instantiated,//That is, the first declaration is not to specify a type, and then specify the type when you want to use (instantiate). Generics can be used for classes, methods, delegates, events, and so on. This is instantiated, defining an array to be sorted int[] Array = {1, 4, 6, 2, 7, 8}; Sort. Bubblesort (array); foreach (var i in array) {Console.WriteLine ("{0}", i); } console.readkey (); }//When we need to rewrite this class when we change the type, what should we do? Instead of declaring what type//public void Bubblesort (int[] array), we use a placeholder to define a method for sorting the array, substituting the type parameter with a placeholder,//does not specify what type, when really making Use time to instantiate public void Bubblesort (t[] array) {int length = array. Length; for (int i = 0, i < length-2; i++) {for (int j = length-1; J >=1; j--) { if (Array[j]. ComparetO (array[j-1]) <0) {T temp = array[j]; ARRAY[J] = array[j-1]; ARRAY[J-1] = temp; } } } } }
2. Generic methods and generic classes
A generic class differs from a generic method in that the generic method reduces the scope of the action, but is limited to the current method, and the scope of the action is no longer the entire class. Specifically, the declaration's coercion type support differs from the location of a generic parameter constraint, where one is defined after the class and the other is defined behind the method, such as showing:
? The scope of a generic class is the entire class
But at this point we find that the entire class is implemented, and if the class is defined as a generic class implementation icomparable simply because of a sort of method, the scope is obviously too large and is not necessary at all, so the generic method appears.
<summary>/// generic class. IComparable is a generic parameter constraint and must implement IComparable interface//</summary>// <typeparam name= "T" > Mandatory type parameter </ Typeparam> public class Supercalculator<t>where t:icomparable { //code: slightly public void Speedsort (t[] array) { //code: slightly } }
? The generic method is just acting on this method
public class Supercalculator { //code: slightly///<summary>//// generic method, at this point the method implements the IComparable, not the entire class. //</summary>// <typeparam name= "T" > Mandatory type parameter </typeparam>// <param name= "Array" > Array name </param> public void speedsort<t> (t[] array) where t:icomparable { //code: slightly } }
3. How to run generics? Reduce the repetition rate of code
Because of the variable type of parameter, want to reduce the repetition rate of code, make the program more refreshing when used, the generic is similar to the template, you can pass parameters for the template as needed. That is the example that we have described above, which will be determined when we push the determination of the parameter type to the implementation. (The first example is that)
? Enhanced flexibility of the program (generic parameter constraints)
When the types of parameters are inconsistent but are compared, the flexibility of the program can be enhanced by running the generic parameter constraints because the standard is not temporary.
For example, if we have a class named book, whose attributes have a title and a price of two attributes, the caption is a string type, and the price is type int, at which point we define an array, including two books, at which time we call our first example of the sorting method, at this point we have to pay attention, since is the sort, So inevitably compare the size, but the type is different, the comparison of the standard where?
The basic way to implement comparisons in. NET is to implement the IComparable method, which we first implement with a non-generic version, which is larger than the latter, returns an integer greater than 0, less than an integer less than 0, and returns 0 when it is equal.
We compare the price to the standard.
Define IComparable Interface Public interface IComparable { int CompareTo (object obj); } Implements the interface, but we found that the call at this point, after the comparison, and there is a downward conversion, because the object is the base class //is the topmost, so to book, is down-conversion, contrary to the Liskov substitution principle, public Class Book:icomparable { private int price; private string title; public book (int price, string title) { this.price = Price; this.title = title; } public int Price {get {return this.price;}} public string Title {get {return this.title;}} public int CompareTo (object obj) {book book2 = (book) obj; Return This.Price.CompareTo (BOOK2); } }
This can be compared, but the ordered Sorthelper generic class does not know, so you need to tell the compiler (sorthelper<t> can be compared), then it needs to implement the interface IComparable.
<summary>////This is a bubble sort, a total of length-1 can be executed. The T in the angle brackets in the class represents the type, which can be passed again because the type is not transitive in the constructor.///</summary>//type parameter constraints public class sorthelper<t> where t:icomparable {//When we need to rewrite this class when we change the type, what should we do? Instead of declaring what type//public void Bubblesort (int[] array), we use a placeholder to define a method for sorting the array, substituting the type parameter with a placeholder,//does not specify what type, when really making Use time to instantiate public void Bubblesort (t[] array) {int length = array. Length; for (int i = 0, i < length-2; i++) {for (int j = length-1; J >=1; j--) { The properties of our incoming books are comparable and can be implemented by the CompareTo method if (Array[j].<span style= "Background-color: RGB (255, 102, 102); " >CompareTo</span> (Array[j-1]) <0) {T temp = array[j]; ARRAY[J] = array[j-1]; ARRAY[J-1] = temp; } } } } }
This enables the use of generic sorting, can support all implementations of the IComparable interface type parameter array, at this point the comparison of the program becomes very flexible.
Where of generics
The where of generics can be qualified for type parameters. There are several ways to do this.
A) the where t:struct restriction type parameter T must inherit from System.ValueType.
b) The where T:class restriction type parameter T must be a reference type, that is, cannot inherit from System.ValueType.
c) where t:new () restriction type parameter T must have a default constructor
D) The where T:nameofclass restriction type parameter T must inherit from a class or implement an interface.
These limits can be combined, for example: public class point where T:class, IComparable, New ()
? Greatly improves the performance and security of collection types
In terms of performance, you can avoid implicit unpacking and boxing problems.
When it's non-generic,
const int listsize = 3; Private static void Usearraylist () { ArrayList list = new ArrayList (); int i = +; List. ADD (i); String value = (string) list[0]; const int listsize = 3; for (int i = 0; I <ListSize; i++) { list. ADD (i); The list's add is an object of type objects, here is a boxed operation (converting a value type to a reference type) } for (int i = 0; i < listsize; i++) { int Value = (int) list[i]; Cast to int (value type) by the object type (reference type), which is the unboxing Operation Console.WriteLine (value); } }
When generics are
const int listsize = 3; private static void Usegenericlist () { list<int> List = new list<int> (); int i = +; List. ADD (i); String value = (string) list[0]; const int listsize = 3; for (int i = 0; i < listsize; i++) { list. ADD (i); Compile-time type has been determined without boxing } for (int i = 0; i < listsize; i++) { int value = List[i];//compile-time type is OK, no unpacking required
console.writeline (value); } }
if we output it in time, we will find that the execution efficiency of generics is higher than the set.
In terms of security, errors in the compilation process can be found in a timely manner, preventing errors from being hidden. This means that the compile-time type security is guaranteed.
when using a non-generic
ArrayList list = new ArrayList (); int i = +; List. ADD (i); Can be compiled, but at run time may be error, because the compiler does not recognize that //list[0] is an integer, but instead of it as an object type can only be found when the error is run, //At this time the program may have been handed over to the user, Make the error cannot be found in time string value = (string) list[0];
When using generics
list<int> list = new list<int> (); int i = +; List. ADD (i); cannot be compiled because its int type is recognized at compile time and cannot be converted to a string type, thus guaranteeing //the type of security string value = (string) list[0];
Strongly-typed support + generic parameter constraints determine where the parameter type requirements are not met at compile time, ensuring type safety at compile time, thus avoiding type conversion errors at runtime.
4. Benefits of generics
Generics do not force the boxing and unpacking of value types, or downward-forcing type conversions on reference types, so performance is improved. By knowing the type limits of variables defined using generics, the compiler can validate the type hypothesis at a much higher level, so generics increase the type safety of the program. It allows programmers to defer the specification of an actual data type until an instance of the generic is created.
In short, generics can greatly improve the reusability of code, while also obtaining strong-type support to improve application performance.
. NET Generics Learning