C # feature review-generic

Source: Internet
Author: User
ArticleDirectory
    • Basic Introduction
    • Generic Constraints
    • Generic internal implementation
    • Summary

I believe everyone is familiar with this feature of generic and. net. When talking about generic, we can't help but mention templates in C ++, and the introduction of templates in C ++ has greatly improved.CodeThe reusabilityProgramMembers. Therefore, in. NET 2.0 and Java 1.5, which are both strong language platforms, they also introduce generic support for languages and platforms. However, although the three languages ultimately provide the type parameterization function, the implementation of this function in the three platforms or languages is significantly different. Relatively speaking, the C ++ template function is the most powerful among the three, but because. net and Java have higher requirements on type security and stability, and their support for generics is slightly simpler, but even so, the implementation of generic features in the two camps has also aroused debate among programmers in the two camps. However, Java's pseudo-generic (wiping method) is generally considered to be comparable. net's JIT-level real generic performance is poor (Java still has packing and unpacking operations ). Of course, these are post-statements. Let's take a look at how to use. Net generics!

Basic Introduction

.. NET 2.0 and later support the use of generics in many types, including classes, structures, interfaces, delegation, and method members, the generic type is the same as the class type. It even supports the implementation of the same interface but different generic types, which is somewhat similar to the implementation of overload at the class level. Finally,. Net allows you to define multiple generic types at the same time.

The generic type in generic methods is basically the same as that used in classes. However, a convenient way for programmers is its type inference function, this means that programmers can use these methods just like common methods, while enjoying the convenience of generics. E.g.

Code

    Static     Void  Test  <  T, U  >  (T, U u ){}
Static Void Main ()
{ // In a function, we do not need to declare the parameter type. The Compiler automatically
// Automatic Inference type
Test ( 10 , " 20 " );
Test ( 1.1 , 2.2 );
}

Next, let's take a look at some precautions for Using Generics in. net.

1. Use of generics in nested classes. Nested subclass automatically inherits (?) The generic type of the package class. Of course, you can overwrite the type of the package class in the nested class, but the compiler will issue a warning during compilation to remind users to avoid writing by mistake. E.g.

  Class  Container  <  T, U  >  
{
// The compiler will issue a warning here
// Tell the user that the generic and package classes here are the same
Class Nested < U >
{
Void Method (T P0, u P1)
{
}
}
}

2. Problems of coordination and inverter. The definition of covariant and inverter is simply to say whether generic types allow conversions between child classes and parent classes. We will not discuss it in detail here. If you are interested, please refer to this article. Before. Net 4.0, we did not support covariant and inverter, which made our code sometimes awkward. The following is a simple example (Note: This example is only for illustration and is not necessarily appropriate ).

First, we define two data types: idata and ioperation:

  InterfaceIdata {VoidMethod ();}
InterfaceIoperation<T> WhereT: idata {VoidRun (t data );}

Then we define different types of data and operation classes:

Code

  Class  Adddata: idata {
Public Int A1, A2;
Public Void Method (){}

}
Class Add: ioperation < Adddata > {
Public Void Run (adddata D)
{
Console. writeline (D. A1 + D. A2 );
}
}
Class Complexdata: idata {
Public Void Method (){}
Public Int A1, A2, B1, B2;
}
Class Complexadd: ioperation < Complexdata > {
Public Void Run (complexdata D)
{
Console. writeline ( " {0} + {1} I " , D. A1 + D. A2, D. B1 + D. B2 );
}
}

If this method can be used, we think it should be safe:

  Ioperation<Idata>OPR= NewAdd ();
OPR. Run (data1 );
OPR= NewComplexadd ();
OPR. Run (data2 );

However, such Code cannot be compiled. Although we know that their use is absolutely safe, because adddata or complexdata is a subclass of idata. Fortunately, in. net4.0, programmers will not have this worry.

3. Generics do not support operators. Templates in C ++ support operators. However, since operators are static and determined during compilation (see this article ), therefore, the runtime generics cannot implement this operation between types. Although you can use interfaces to achieve the same function, convenient operators cannot be supported in generics. This is a disadvantage of C # generics, because it is useful in many cases. In the same way, because the feature is determined during compilation, although you can define a generic feature class, you cannot use it. For more information, see. e.g.

 
  ClassMygenericattribute<T>: Attribute
{
}
[Mygeneric]
ClassMyclass
{
//This Code cannot be compiled
}

4. type conversion of generics. Generics cannot be converted directly from other types (except objects). In this case, there are two ways to convert other types to generic objects, one is that the generic constraint is a class or a base class, which can be converted through the as operator, such as return somevalue as T. But sometimes if we don't know the generic type or the generic type is struct, how can we convert it? The answer is that through two type conversions, we first convert the object to be converted into an object, and then forcibly convert the object to T, e.g. return (t) (object) somevar. For specific examples, refer to this article.

Finally, there is a keyword "default" in the generic type. As the name suggests, it provides the default value when the reference type and value type are not initialized. The default value of the reference type is null, and the value type is 0.

Generic Constraints

If. net only appears in the generic type but does not have the generic type constraints. I think the generic functions will be greatly compromised. It is precisely because of the generic type constraints that, this makes these types more standardized and accurate. This is also more secure than the C # template with the same strong type.

Like when declaring an inheritance relationship for a class, a generic constraint can declare multiple interfaces and a maximum of one base class constraints. If a base class constraint is declared, class constraints must be placed at the top of the constraints, which is the same as the requirements for class inheritance. In addition, the declared constraint class cannot be a SEAL class or some special structures (such as nullable <t>). For example, we cannot declare the constraint class as string or system. nullable <t>. finally, like declaring the inheritance relationships of multiple interfaces in the class, the constraints of the generic type are the and rather than the or relationship. That is to say, if you add multiple constraints, all constraints must be met for generic usage.

We can use the keywords class and struct to determine whether the type is a value type or a reference type. However, the base class constraints indicate whether the generic type is a class or a structure, therefore, we cannot use both the class or struct constraints and the base class (structure) constraints. g. class classa <t> where T: baseclass, class is not allowed. Note that the class and struct constraints must be prior to any other constraints.

Another constraint keyword worth noting is new (). The New Keyword means that a generic object must provide a non-argument constructor. Note that new () constraints must be placed at the end of all constraints. This constraint is sometimes useful, but sometimes it looks more like a chicken. First of all, although the new () Constraint indicates that you can use the new () operator to instantiate an object for a generic object in the class, the instantiation of this object in the pencil is still implemented through reflection, that is, t a = new T () is equivalent to t a = system. activator. createinstance <t> (); this reduces the program efficiency. On the other hand, the new constraint only supports the constructor without parameters, but does not support the constructor constraints of user-defined parameters. Although you can pass parameters by using the factory method, but after all, it is not free enough, which makes the new () Constraint sometimes useless.

The constraints do not support delegation and enumeration types. For example, you cannot define the class classa <t> where T: Delegate. this is because delegation and enumeration are considered special classes and cannot be specified as type parameters. The compiler cannot perform the compiler type check based on delegate.

The last type constraint supports inheritance, but you must re-declare all the constraints of the parent class when defining the generic type in the subclass. The starting point of the designer is to allow the programmer to know where the constraints in the Child classes come from and reduce doubts. But from another perspective, this will allow programmers to add more duplicate code, even if you already know what constraints it has.

Generic internal implementation

In. net, generics are truly supported at the platform level. In C #, generics are also objects. In fact, the compiler will convert generic parameters into special metadata during compilation, and the CLR will generate its actual type as needed. To avoid packing and unpacking, the generic Implementation of the value type is different from that of the reference type. Let's take a look at the differences between them.

1. Value Type generic Object Instantiation

When a value type is used as a parameter to construct a generic type for the first time, the runtime creates a specialized generic type and substitutes the provided parameters into the appropriate location in the msil. A dedicated C # generic type is created for each unique value type used as a parameter. This type of generic class is actually equivalent to local code containing a specific value type, which will be very helpful for performance improvement.

2. instantiate a generic object of the reference type

For reference types, generics work in slightly different ways. When any reference type is used to construct a generic type for the first time, the runtime creates a specialized generic type. Replace the parameter in msil with an object reference (or a better pointer). Then, each time the object reference is used as a parameter for instantiation. When constructing a type, the runtime will reuse the dedicated version of the previously created generic type regardless of the detailed type of the reference type. This is because all objects reference the same size.

Summary

You can see generics everywhere in the. NET class library, especially in arrays and collections. The existence of generics also greatly improves the development efficiency of programmers. More importantly, the C # generic type is more secure than the C ++ template, and the performance is improved by avoiding packing and unpacking operations. Therefore, it is necessary for us to master and make good use of this powerful language feature.

 

Reference books:

Essential C #2.0 by Mark MichaelisJuly 13,200 6

 

Note: it is not long before you decide to write more time periods. Therefore, the article will inevitably have many vulnerabilities. If you can point out, I think it will be helpful for me to clarify my ideas. At the same time, I also hope that the things I wrote will be helpful to you, so that I will be very happy.

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.