Why use C # generics?
To understand the problem, let's look at the following code, which omits some of the content, but the function is to implement a stack that can handle only the INT data type:
public class Stack {PRivate int[] m_item, public int Pop () {...} public void Push (int item) {...} public Stack (int i) {thi S.m_item = new Int[i]; The code above works fine, but what happens when we need a stack to hold the string type? Many people would have thought of copying the above code, and changing int to string. Of course, this does not have any problem in itself, but a good program is not to do so, because he thought that if you need a long, node type of stack to do? Do you want to copy it again? A good programmer would think of using a common data type object to implement this stack:
public class Stack {private object[] m_item, public object Pop () {...} public void Push (object item) {...} public Stack (int i) {this.m_item = New[i];}} This stack is well written, he is very flexible, can receive any data type, can be said once and for all. But in a comprehensive manner, it is not without blemish, and it is mainly manifested in:
When a stack processes a value type, a boxing, folding operation occurs, which allocates and reclaims a large number of variables on the managed heap, and if the amount of data is large, the performance penalty is severe.
When working with reference types, there is no boxing and folding operations, but the use of a data type cast operation increases the burden on the processor.
There are more serious problems with casts on data types (assuming that the stack is an instance of a stack):
Node1 x = new Node1 (); Stack. Push (x); Node2 y = (Node2) stack. Pop (); The above code is completely no problem at compile time, but because of the push of a Node1 type of data, but in the pop is required to convert to the Node2 type, this will occur when the program runtime type conversion exception, but escaped the compiler check.
For the problem of the object type stack, we introduced generics, and he can solve these problems gracefully. Generics use a passing data type T instead of object, specifying the type of T when the class is instantiated, and the runtime (runtime) is automatically compiled into local code, and the efficiency and code quality are greatly improved, and the data type is guaranteed to be secure.
Using C # generics
The following is a generic to rewrite the stack above, with a generic data type T as a placeholder, waiting to be instantiated with an actual type instead. Let's take a look at the power of generics:
public class Stack {private t[] m_item, public T Pop () {...} public void Push (T item) {...} public Stack (int i) {this.m_it EM = new T[i]; }} class is not changed, just the introduction of a generic data type T can be applied to any data type and is type-safe. The calling method for this class:
Instantiation can only hold class Stack a = new stack (100) of type int; A.push (10); A.push ("8888"); This line of compilation does not pass because Class A only receives data of type int x = A.pop (); Instantiation can only hold a string type of class Stack B = new stack (100); B.push (10); This line of compilation does not pass because Class B receives only the string type of data B.push ("8888"); String y = B.pop (); There are distinct differences between this class and the class implemented by object:
1. He is type-safe. If you instantiate a stack of type int, you cannot handle data of type string, and so do other data types.
2. No packing and folding boxes are required. This class, when instantiated, generates local code according to the data type passed in, and the local code data type is determined, so no boxing and folding boxes are required.
3. No type conversion is required.
Theoretical knowledge:
Generics: A parameterized type that enables the operation of multiple data types on the same piece of code. Generic programming is a programming paradigm that abstracts types using "parameterized types" for more flexible reuse.
C # generics give code a stronger type-safe, better reuse, higher efficiency, and clearer constraints.
C # Generic capabilities are supported by the CLR at run time, and are distinguished from the compile-time template mechanism of C + + and Java's compile-time "wiping method". This enables generic capabilities to interoperate seamlessly across the languages that support the CLR.
C # generic code, when compiled into IL and metadata, uses special placeholders to represent generic types and supports generic operations with proprietary IL directives. And the true generics instantiation works in a "On-demand" way, at JIT compile time.
The C # Generic compilation mechanism is as follows:
At the first round of compilation, the compiler produces only the "generic" IL Code and metadata for the stack type, does not instantiate the generic type, and T only acts as a placeholder in the middle.
At JIT compile time, when the JIT compiler encounters the stack for the first time, the "generic" Il Code and the T in the metadata are replaced with the int type-the instantiation of the generic type.
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.
Several features of C # generics
If the parameters of the instantiated generic type are the same, the JIT compiler reuses the type, so the dynamic generic capability of C # avoids the problem of code bloat that could be caused by C + + static templates.
C # Generic types carry rich metadata, so the generic types of C # can be applied to powerful reflection techniques.
C # Generics use the "base class, interface, constructor, value type/reference type" constraints to implement "display constraints" on type parameters, improve type safety, and lose the high flexibility of the C + + template's implicit constraint based on "signature".
C # generic classes at compile time, Mister into intermediate code IL, generic type T is just a placeholder. When instantiating a class, replacing T with a user-specified data type and generating native code from the immediate compiler (JIT), the native code already uses the actual data type, equivalent to a class written in the actual type, so the local code of the different enclosing classes is not the same. According to this principle, we can think that: the different enclosing classes of generic classes are different data types respectively.
This way, generics are not only more flexible, but also easy and up-to-the-level code! No need to write specific code for a different overloaded method!
C # Generics are an invaluable asset in the development tool library. They can improve performance, type safety and quality, reduce repetitive programming tasks, and simplify the overall programming model, all done through elegant, readable syntax. Although the C # generics are rooted in C + + templates, C # raises generics to a new level by providing compile-time security and support. C # leverages two-phase compilation, metadata, and innovative concepts such as constraints and general methods. There is no doubt that a future version of C # will continue to evolve generics in order to add new functionality and extend generics to other. NET Framework areas such as data access or localization.
The above is about the use of C # generic content, more relevant content please pay attention to topic.alibabacloud.com (www.php.cn)!