.NET Generics VS C Templates
Liu Weipeng / article
C Louvre (http://blog.9cbs.net/pongba)
When there is no introduction of templates in C , the parent Stepanov C STL is sharply found. Object-oriented theory does not describe all existing structures, for example, algorithm is not an object, and then go deep, he has a lot The abstract logic of the algorithm does not rely on the object of the object it and the underlying data structure. That is, the logic of the algorithm can be abstracted separately, so he tries to describe this abstraction with C at the time, while at the time C does not support generics, resulting in this similar description of algorithms very complicated, similar to this similar structure (algorithm and container are two components of STL, both through iterators "bonded "stand up). The template has been added later in C , and it has to be largely the result of Stepanov's efforts. This idea had to describe "genius" in the case where the object theory is in one hand, it has directly affected C "post".
The generic can support the high degree of reuse of the code in almost no loss of efficiency, and have mathematical abstract beauty (this contact with the STL source code is very clear). Thus, generics immediately become one of the light characteristics of C .
Now, .NET and Java also realize the importance of generics - although they have a single characteristic, but inherited algorithm abstract description is "strong binding", inefficient, object-oriented The extra burden of state is invisible. However, generic algorithm abstract description is "non-bound", efficient, any object that meets grammar and semantic requirements can be passed to it as a parameter, and the nature of generics is to generate a copy for each object. Separate code (that is, the so-called "instantiation"), this tape-made code has high efficiency, strong type, no support and burden, .NET and JAVA Introducing generics in the middle can be said to be synthesized. However, due to .NET and Java language essence (interpretation), there is a very difficult technical gap, which is difficult to pass over, which will be mentioned below.
Let's talk about the generic implementation in .NET. As for its grammar, it is secondary, and people who know a little about C templates are not difficult to see from several line samples.
In fact, the essence of generics is quite simple and intuitive. It is clear that people in the macro are clear. Some simple generic code can be macro in the premise of removing type safety. That is, the compiler is responsible for instanting each episode of each episode parameter from each episode to instant a template entity.
Maybe you will say, is this not almost the same as C ? Yes, the idea is the same, but it is different from it.
The instantiation of the generic code of .NET is performed at the runtime period, this is different from C . In the .NET generics, it is only a simple reference to the compile period, and the instantiation of the corresponding class is performed by the CLR running layer, so the .NET generics is part of the platform, not like C That is, it is part of the compiler.
The instantiation of the runtime is made by the CLR to bring a significant benefit to the .NET generics: avoid code expansion. In C , the template located in two different compilers is likely to cause two identical code, and the template instances instantiated by two episodes of different template parameters may not be shared. However, in .NET, the CLR knows everything, so there is no three cases of the same instantiated code in two assembly, and the unssembled code in an assembly can be used for another assembly, even even Some code can also be shared between different instances of the same template. The characteristics of such code sharing can ease the code expansion to some extent. However, .NET's generics also have some weaknesses. In the event of an instantiation, it determines that it cannot perform certain complicated type derivation (this will cause JIT speed slow), that is, traits technology widely used in STL and Boost libraries are destined to touch in .NET. bump. The language characteristics of supporting complex type derivation techniques are offset, which explains why .NET does not support the reasons for offsetting (even connected). However, Traits are also a desirable architecture and efficiency must be [1]. Therefore, in (running period) efficiency, .NET cannot be compared with C .
In addition, .NET generic supports constraint, so-called constraint, is constrained on the template shape. These constraints in .NET are mainly, such as: inheriting from a base class, which interfaces are implemented, and whether there is a non-arranging PUBLIC constructor. There are two cases: If you do not introduce constraints, there are two cases: First, for some templates, instantiated code cannot be compiled by JIT, but because of the compilation of generic code is running The period is performed by the CLR operating layer, so the compilation error at each time may reflect [2] by an abnormal manner, however, that is, this may result in a lot of unnecessary compilation, that is, the CLR may be compiled After many of the code, I found a compilation error, so the previous compilation is wasted. Second, the method of solving the first case is to force the conversion, for example, if you want to call COMPARETO to an object (the type of object is template), you have to convert the object to the iCompABLE interface. This can solve the problem, but add unnecessary runtime overhead. Therefore, C # uses constraint so that if the mediate does not meet the requirements (for example, there is no specific member function), it can be found in the compile period, which ensures the strong type of check of the compile period, and reduces the operation cost overhead. As a comparison, C does not support Constraint, as for the reason Stroustrup is very clear in D & E. C does not exist as problems mentioned above, and CONSTRAINT in C can simulate [3] by other means [3].
Overall, .NET is different from C "Different", the level is different, and the generic feature in .NET has these simple features for it, because .NET is much more than C information in the runtime. (Add the advantages of single inheritance), so some work can be given to the type identification or Reflection of the running period, and it is relatively simple and concise, which is relatively small, and .NET's language characteristics are relatively simple. Avoid some complicated work. As the compiled language, C is almost lost all structural information and type information (TypeInfo only contains a relatively small part of information), so C must be better in the compile period, so that the numerous characteristics of the C template is Indispensable. The reader may wish to compare the .NET's Delegate with the Boost :: Signal in the Boost library, see how much work has been made in order to achieve a perfect "callback" system. The former has a single structure and the support of Reflection, which is much simpler. So, although .NET generics are simple, but it is tailored, and C generics is complicated, but it is necessary. Each of them takes the required, and there will be a lot of martial arts in their respective languages. As for the exception of the best, the language expert, the contrast here is to let readers have a general understanding of the two.
[1] TRAITS's role means "transmission of type information" and "What types of things to do" is "for which types of information", which is necessary for a robust compile period.
[2] In fact, suppose this existence, then the abnormality thrown by the CLR will not be able to be captch by the user, unless the use of the template is in the exception TRY - this is obviously unfriendly.
[3] Interested readers can refer to the relevant part of the BOOST library. This approach to C can avoid increasing the collection of language characteristics and avoids too much keywords.