Generic 101 in. net

Source: Internet
Author: User
1.1.1 Summary

Figure 1 C # Introduction to generics

Before getting started with generics, we usually use specific types (char, Int, String, etc.) or custom types to define our variables. If we have a very powerful interface, in addition, we want to extract or reconstruct it into a common interface, so that this interface is not only applicable to the defined data type, but also to more data types, so as to facilitate future expansion.

Generics provide the implementation of the above functions. Generics actually provide an abstraction layer of the data type, which is so abstract as to facilitate ourCodeWe do not need to specify the data type in the hard-code interface, but specify the Data Type through an abstract generic type. Therefore, a generic interface can be extracted. Next, let's use specific examples to illustrate what a generic type is.

1.1.2 body 1.1.1.1 no generic C #1.0

I believe that many people have used stacks or other classic data structures, and are familiar with Stack Filo. Suppose we want to define a stack to store specific data types, such as int data. OK allows us to implement custom stacks.

/// <Summary> ///A custom stack1./// </Summary>Public classCustomstack1{Private int_ Stackpointer = 0;Private int[] _ Stackarray;Public voidPush (IntITEM ){//// Concrete implemention.}Public intPop (){//// Concrete implemention.}}

For simplicity, we do not fully abide by the OOP principles. Here we do not use the specific implementation of attributes and Methods. Now we have the first version of the stack that can store int data types. However, if you want to change the storage data type, add a string. So how can we implement it? Yes, we only need to add a stack of the string type.

/// <Summary> ///A custom stack2./// </Summary>Public classCustomstack2{Private int_ Stackpointer = 0;Private string[] _ Stackarray;Public voidPush (IntITEM ){//// Concrete implemention.}Public StringPop (){//// Concrete implemention.}}

Soon we completed the second version of the stack, which seems very simple and quickly implemented only by Ctrl + C and CTRL + V, but is our code really easy to maintain? Think about the crisis. Can we define the stored data type as a general type (abstract data type) at the beginning )? ---- Evil object.

  //  ///   A custom stack.   //    public class   customstack  { private int  _ stackpointer = 0;  private object  [] _ stackarray;  Public void  push ( Object  item) { /// concrete implemention. }< span style = "color: Blue"> Public object  POP () { /// concrete implemention. }

Now we have implemented the stack of the third edition. It seems that we have found a common solution. Think about it. We should note that if we save and retrieve the data type as the value type, the value type requires boxing and unboxing operations (《. net Value Type and Reference Type 101), and also performs data type detection. If the data volume is small, we may not be able to detect performance changes, but the data volume is large .... This is one of the reasons why we want to use generics, but more importantly, we need to provide more information to the compiler during boxing and unboxing, type check is performed based on the information we provide during compilation.

Generic Type in 1.1.1.2 C #

Now we know why. NET provides generics. Now let's learn what generics are and how to implement them! C #2.0 provides the generic mechanism, but this is not a novel technology, because both C ++ and Java have provided generic mechanisms.

C # provides the following types of generics: classes, structs, interfaces, delegates, and methods.

    • Generic Type

Some people may say that they have never used C ++ templates or Java generics, and do not know C # generics. Is that true? In fact, we often use generics. I believe many people have used dictionary <tkey, tvalue>. Yes, this is the generic dictionary provided in C, next we will introduce the custom generic class mmstack.

Figure 2 generic type

/// <Summary> ///A custom generic stack./// </Summary>Public classCustomstack<T> {Private int_ Stackpointer = 0;PrivateT [] _ stackarray;Public voidPush (T item ){//// Concrete implemention.}PublicT POP (){//// Concrete implemention.}}

The implementation of the generic class customstack is given above. We found that you only need to add <t> after the class name and change the specific data type to the abstract generic type T, now we have defined a simple generic class. We can compare the differences between non-generic and generic implementations through the following.

Figure 3 Non-generic and generic class definitions

We found that the implementation of generic mmstack and non-generic customstack is not much different. We only need to replace the specific type with T, next we will go to generic advanced learning.

    • Generic Delegation

For more information, see 《Delegate in. netAnd 《Delegate and event in. Net (continued)Now let's take a look at generic delegation.

Figure 4 Definition of generic delegation

Given the definition of generic delegation, we should note that type parameters includes generic parameters and return types. With the reference of the C #3.0 LINQ feature, the use of generic delegation has been greatly expanded. Let's talk about how to use generic delegation through specific code.

First, we define a generic delegate, and then define a calc class. Then we define two methods in Calc: add () and divide () as follows:

 /// <Summary> ///  Define generic delegate.  /// </Summary>  Public Delegate Tr Calcmethod <T1, T2, tr> (T1 X, T2 y ); Public class  Calc { Static private double SUM; /// <Summary> ///  Gets or sets the sum.  /// </Summary> /// <value> ///  The sum.  /// </Value>  Static public double Sum { Get { Return SUM ;} Set {Sum =Value ;}} /// <Summary> ///  Adds the specified X.  /// </Summary> /// <Param name = "X">  The X.  </Param> // <Param name = "Y">  The Y.  </Param> /// <returns> </returns>  Static Public String Add ( Int X, Int Y) {sum = x + y; Return Sum. tostring ();}/// <Summary> ///  Divides the specified X.  /// </Summary> /// <Param name = "X">  The X.  </Param> // <Param name = "Y">  The Y.  </Param> /// <returns> </returns>  Static Public String Divide ( Int X, Int Y ){ If (Y = 0 ){ Return  "The divisor cannot be zero" ;} Sum = x * 1.0/y; Return Sum. tostring ();}}

Next we need to define a delegate variable, and then bind the delegate variable to the specific call method.

 
/// Initialize engeric delegate instance to add method.Calcmethod<Int,Int,String> Calcmethod =NewCalcmethod<Int,Int,String> (Calc. Add );
    • Type Constraints

In the previous example, we didn't limit generic types. Because t is an abstract type, sometimes we have to limit what type T is. For example, we can define customstack <int>, the stack of the customstack <double> or customstack <string> type, but sometimes we must limit the generic type. In this case, we need to use the type constraint to introduce the keyword ---- where.

In C #, five types of constraints are provided (Class Name, Interface Name, reference type, value type, and constructor). We can use different type constraints to limit the generic type.

Type Constraints

Constraint description

Classname

T can only be this class or inherit the subclass of this class

Interfacename

T can only be this interface or the type that implements this interface

Struct

T is any value type

Class

T is any reference type (such as classes, arrays, delegates, and interfaces)

New ()

T is any type of function with public parameters and no arguments.

Table 1 type constraints

Through table 1, we initially understand the differences between different types of constraints. Now let's take a look at the specific examples of their use scope and differences.

Suppose we have defined a generic struct refsample <t> where T: class. Now, the following examples are applicable to the class constraints (indicating the difference between the value type and the reference type ):

A. refsample <idisposable>

B. refsample <string>

C. refsample <int []>

D. refsample <guid>

E. refsample <int>

The exciting time has come. Now let's announce the answer quickly! The answer is ABC, because the generic constraint is a reference type constraint. If you are not clear about it, please refer to the definition of the reference type constraint.

In the example of a class constraint, we refer to the inverse three-Value Type constraint as that of a value type.

OK. Let's introduce the constructor constraints. Before introducing constructor constraints, let's review the conditions that meet the constructor constraints: any value type, any non-static non-abstract class without explicit definition of constructor and any non-abstract class with clear definition of non-argument constructor. This sentence is awkward. Let's explain it through a specific example.

/// Define generic method /// which has constructor type constraintsPublicT createinstance <t> ()WhereT:New(){Return newT ();} createinstance <Int> (); Createinstance <Object> (); Createinstance <String> ();

Now we have defined a generic method and added constructor constraints. createinstance <int> () and createinstance <Object> () are called successfully, but createinstance <string> () fails to be called, this is because the string class does not provide a non-argument constructor. Someone may ask, "it is difficult for us to determine whether each type contains the default construction of a non-argument function ", this is indeed the case, but we can remember that the C # specified value type provides the default no-argument constructor.

 

    • Combination Constraints

In the previous generic example, only one type constraint is used, but sometimes we need to use multiple types of constraints. In this case, we can use combination constraints, when using constraints, pay attention to the order of constraints. The order of constraints is as follows:

Figure 5 constraint order

We found that classname, class and struct are the main constraints, interface names are the second constraints, and finally the constructor constraints. OK now we have a preliminary understanding of the combination constraints, so let's use the following example to deepen our understanding.

A. class sample <t> where T: Class, struct

B. class sample <t> where T: stream, Class

C. class sample <t> where T: New (), stream

D. class sample <t> where T: idisposable, stream

E. class sample <t> where T: xmlreader, icomparable, icomparable

F. class sample <t, u> where T: struct where u: Class, T

G. class sample <t, u> where T: stream, u: idisposable

The preceding example shows the incorrect combination constraints (Note: ~ E single-type combination constraints and Fg multi-type combination constraints). Please point out the cause of the constraint error. If you are not clear about the cause of the error, let's recall the constraint definition.

1.1.3 Summary

This article introduces the basic knowledge of C # generics and provides its own summary. This is not all of C # generics, if you want to learn more about generics after reading this article, this is my goal.

Advantages of generics:

    • Check the type during compilation to reduce the running exception invalidcastexception.
    • The generic type uses a strong data type. For example, if we use the customstack <customstruct> Object objstack, The customstruct is successfully pushed to the stack by calling the push () method, but the objstack. Push ("stack") fails.
    • Boxing and unboxing operations are not required for value types. For example, boxing and unboxing operations are not required when the previous generic push () and POP () methods are used to store and retrieve value types.
    • Reduce the amount of code. For example, if we define a generic stack, we do not need to define the stack of the int and string types as in the previous example.
    • ProgramPerformance is improved because no type conversion is required to reduce type detection.
    • Use generics to reduce memory consumption. Because boxing is not required, heap space does not need to be re-allocated.
    • The code is more readable.

Many people like to compare the generics in C #, C ++ and Java, and have many discussions about them. Here I also give my own ideas, I think the generic functions of C ++ are indeed more powerful than those of C # and Java.

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.