C # runtime generics

Source: Internet
Author: User

C # runtime generics

There is almost no difference between the compilation methods of generic classes and those of general classes. In fact, the compilation result is only metadata and intermediate language (IL ). Of course, to accept the types provided by users in the code, il should be parameterized. The usage of generic il varies depending on whether the type parameter is a value type or a reference type.

When the value type is used as a parameter to construct a generic type for the first time, the runtime replaces the corresponding location in Il with the provided parameter to create a specialized generic type. For each unique value type used as a parameter, a dedicated generic type is created at one time.

For example, assume that the program code declares a stack composed of integers:

Stack<int> stack;

In this case, a dedicated Stack class is generated during the runtime, and the corresponding parameters of this class are replaced with integers. Now, the generated dedicated Stack class will be used repeatedly at runtime no matter when the program code uses an integer stack. The following example creates two instances of an integer stack. Each instance is created using the code generated during the running of the integer Stack:

Stack<int> stackOne = new Stack<int>();Stack<int> stackTwo = new Stack<int>();

However, if another stack class is created elsewhere in the program code and different value types (such as long integer or user-defined structures) are used as their parameters, the runtime generates other forms of generics, and then replaces the long integer parameter in the corresponding location of Il. The advantage of creating a dedicated class for a generic type constructed using a value type is that it can achieve better performance. After all, each dedicated generic class contains a value type in "local", so no conversion is required.

Generic and reference types work in a slightly different way. When any reference type is used to construct a generic type for the first time, the runtime replaces the parameters in Il with object references to create a specialized generic type. Then, whenever the reference type is used as the type of the parameter instantiation construction, no matter what type is constructed, the previously created dedicated generic type will be reused during the runtime.

For example, assume that there are two reference types, the customer class and the order class, and then create a stack of the customer type:

Stack<Customer> customers;

At this time, a dedicated Stack class will be generated during the runtime. This class does not store data, but stores the reference of the subsequently filled object. Assume that the next line of code creates a stack of other reference types, called order:

Stack<Order> orders = new Stack<Order>();

Unlike the value type, instead of creating another dedicated Stack class for the order type, you create an instance for the dedicated Stack class and set the orders variable to reference it. For each object reference that replaces the type parameter, the memory space is allocated according to the size of the order type, and the pointer is set to reference this memory location. Assume that you subsequently encounter a line of code used to create a stack of the customer type:

customers = new Stack<Customer>();

Like the Stack class created using the order type, another instance of the dedicated Stack class is created, and the pointer contained in the class is set to reference the memory area of the customer type. Because different programs vary greatly in the number of reference types, therefore, the implementation of Generic C # reduces the number of reference types to the number of specialized classes created by the compiler for generic classes of reference types, greatly reducing the code expansion speed.

In addition, when a Generic C # class is instantiated using a type parameter (either a value type or a reference type), you can use reflection and the actual type for query at runtime, you can also determine its type parameters.

C #Differences between generics and Other implementations

There are significant differences between C ++ templates and C # generics. C # The generic type is compiled into Il, which intelligently creates the corresponding private type for each value type at runtime, while only one private type is created for the reference type; the C ++ template is actually a code expansion macro, which generates a special type for each type parameter provided to the template. Therefore, when the C ++ compiler encounters a template (such as an integer stack), it will extend the template code to the stack class and include the integer as the type of the class itself. Whether the type parameter is a value type or a reference type, if the linker is not specifically designed to reduce the code expansion speed, the C ++ compiler creates a dedicated class each time, this leads to a much higher code expansion speed than using C # generics.

In addition, the C ++ template cannot define constraints. The C ++ template can only use one member (which may or may not belong to a type parameter) and implicitly define constraints. If the member exists in the type parameter passed to the generic class, the program runs normally. Otherwise, the program fails and may return hidden error messages. C # generics can declare constraints and have strict types, so these potential errors do not exist.

Now, Sun Microsystems has added other generic types to the new Java language (the code name is "tiger. The implementation selected by Sun does not need to be modified by the Java Virtual Machine. Therefore, Sun is faced with the problem of how to implement generics On unmodified virtual machines.

The proposed Java implementation uses a syntax similar to the template in C ++ and the generic syntax in C #, including type parameters and constraints. However, because the processing value type is different from the processing reference type, the unmodified Java virtual machine does not support the generic value type. Therefore, Java generics cannot be effectively executed. In fact, the Java compiler inserts an automatic downward type conversion from the specified constraint (if declared) or basic object type (if not declared) when it needs to return data. In addition, the Java compiler will generate a dedicated type at runtime, and then use it to instantiate any construction type. Finally, because the Java Virtual Machine itself does not support generics, it is impossible to determine the type parameters of the generic instance at runtime, and other purposes of reflection will be severely restricted.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.