A generic explanation of C #

Source: Internet
Author: User

This article focuses on generics in C # because generics have a very important place in C # and are critical for writing high-readability, high-performance code.

What is a generic type?

Generics are a very important new feature in version 2.0 of the C # language and the Common language runtime (CLR).

When programming programs, we often encounter modules that are very similar in function, except that they deal with different data. But there is no way we can only write multiple methods to handle different data types. This time, then the question comes, is there a way to use the same method to deal with different types of parameters? The emergence of generics is specifically to solve the problem, it can be seen that Microsoft is very intimate.

Second, why use generics?

Next, let's look at a piece of code.

 Public classGenericclass { Public voidShowint (intN) {Console.WriteLine ("showint Print {0},showint parament Type is {1}", N,n.gettype ()); }         Public voidshowdatetime (DateTime dt) {Console.WriteLine ("showdatetime Print {0},showdatetime parament Type is {1}", DT, dt.        GetType ()); }         Public voidShowpeople (People people) {Console.WriteLine ("showpeople Print {0},showpeople parament Type is {1}", people, people.        GetType ()); }    }
View Code
Static void Main (string[] args)        {            new  genericclass ();            Generice. Showint (one);            Generice. Showdatetime (DateTime.Now);            Generice. Showpeople (new"Tom"  });            Console.readkey ();        }
View Code  

Show Results:

We can see that these three methods, in addition to the parameters passed in, the implementation of the function is the same. In the 1.1 version of the time, there is no concept of generics, then how to do it. Some people think of the inheritance of one of the three major features of OOP, and we know that in the C # language, all types originate from the same type, and that is object.

     Public classGenericclass { Public voidShowobj (Objectobj) {Console.WriteLine ("showobj Print {0},showobj parament Type is {1}", obj, obj.        GetType ()); }    }        Static voidMain (string[] args) {Console.WriteLine ("*****************object Call *********************"); Generice. Showobj ( One); Generice.            Showobj (DateTime.Now); Generice. Showobj (NewPeople {Id = One, Name ="Tom" });        Console.readkey (); }
View Code

Show Results:

We can see that the goal is to achieve. It solves the readability of the code, but there's a downside to this, and what we do is actually a boxing unboxing operation that loses performance.

Finally, Microsoft released generics at 2.0. Next we use the generic method to implement this function.

Iii. generic type parameters

Before using a generic method, let's take a look at some of the knowledge about generics.

In a generic type or method definition, a type parameter is a placeholder for a specific type specified by the client when it instantiates a variable of a generic type. A generic Class ( GenericList<T> ) cannot be used as-is because it is not a true type; it is more like a blueprint for a type. To use GenericList<T> , the client code must declare and instantiate the constructed type by specifying the type parameter within the angle brackets. The type parameter for this particular class can be any type that the compiler can recognize. You can create any number of constructed type instances, each of which uses a different type parameter, as follows:

genericlist<floatnew genericlist<float>(); GenericListNew genericlist<exampleclass>(); GenericListNew genericlist<examplestruct> ();

In GenericList<T> each instance, each occurrence in the class T is replaced with a type parameter at run time. With this substitution, we have created three valid objects of type safety by using a single class definition.

III. generic constraints

When you define a generic class, you can impose restrictions on the types of types that client code can use for type parameters when instantiating a class. If the client code attempts to instantiate a class using a type that is not allowed by the constraint, a compile-time error occurs. These restrictions are called constraints. Specifies a constraint by using the where context keyword. The following table lists the six types of constraints:

where T: struct (the type parameter must be a value type.) You can specify any value type other than Nullable. )

class Myclass<u>        wherestruct /// constraint U parameter must be "value type" Public void Mymetod<t>(T t)       wherestruct  {           }

Where T: Class (the type argument must be a reference type; This also applies to any class, interface, delegate, or array type.) )

class Myclass<u>        whereclass /// constraint U parameter must be "reference type" Public void Mymetod<t>(T t)       whereclass  {           }

where T:new () (the type parameter must have a public constructor with no arguments.) When used with other constraints, the new () constraint must be specified last. )

class where New (){    // ...}

where t:< base class name > (the type parameter must be the specified base class or derived from the specified base class.) )

 Public class employee{}  Public class where T:employee

where t:< Interface name > (the type parameter must be the specified interface or implementation of the specified interface.) You can specify multiple interface constraints. The constraint interface can also be generic. )

 /// <summary>    ///Interface/// </summary>    InterfaceIMyInterface {}/// <summary>    ///A dictionary type that is defined/// </summary>    /// <typeparam name= "TKey" ></typeparam>    /// <typeparam name= "Tval" ></typeparam>    classDictionary<tkey, tval>wheretkey:icomparable, IEnumerablewhereTval:imyinterface { Public voidAdd (TKey key, Tval val) {}}

where T:u (the type parameter provided for T must be a parameter supplied for u or derived from the parameter supplied for U.) Which means the parameters of T and U must be the same)

class List<t>{    voidwhere u:t {/*... */ }}

The above is a simple example of six generics, of course, the generic constraint is not only applicable to classes, interfaces, and generic delegates are equally applicable for generic methods.

Iii. generic methods

 Public classGenericclass { Public voidShowt<t>(T t) {Console.WriteLine ("showt Print {0},showt parament Type is {1}", T, T.gettype ()); }    }Static voidMain (string[] args) {Console.WriteLine ("***************** generic method call *********************"); Generice. Showt<int> ( One); Generice. Showt<DateTime>(DateTime.Now); Generice. Showt<People> (NewPeople {Id = One, Name ="Tom" });        Console.readkey (); }
View Code

Show Results:

It's the same, and now we're finally achieving the results we want to achieve. We can see that no matter what method is called, the last type we get out is the original type. We know that the use of object acquisition is to take advantage of the inheritance of this feature, when the compiler compiles, our incoming parameters will be boxed operation, when we get the time to do the unpacking operation, this method will wear performance. So what is the principle of the implementation of the generic method? First, we need to know that generics are a syntactic sugar, and when we call a generic method, the compiler compiles it to determine the type of the parameter passed in, thus generating the copy method. This copy method and the original method of the method, so there will be no boxing unboxing operation, there is no loss of performance of the matter.

Iv. generic type

Generic classes encapsulate operations that are not specific to a particular data type.

Typically, creating a generic class starts with an existing concrete class, and then changes the type to a type parameter one at a time until generalization and availability are optimally balanced.

When creating your own generic classes, you need to consider the following important considerations:

    • Which types are to be generalized as type parameters.

In general, the more types you can parameterize, the more flexible your code and the more reusable it is. But over-generalization can make it difficult for other developers to read or understand the code.

    • What constraints, if any, are to be applied to the type parameter

One useful rule is to apply the greatest degree of constraint while still handling the types that must be handled. For example, if you know that a generic class is only used for reference types, apply a class constraint. This prevents the class from being used unexpectedly for value types, and allows you to use the as operator on T and check for null values.

    • Whether to decompose the generic behavior into base classes and subclasses.

      Because generic classes can be used as base classes, the same design considerations for non-generic classes also apply here. See the following article later in this topic for rules that inherit from a generic base class.

    • Implements a generic interface or multiple generic interfaces.

class Basenode {} class Basenodegeneric<t> {}//  Concrete typeclass nodeconcrete<t> : Basenode {}//closed constructed typeclass nodeclosed<t>: Basenodegeneric <int> {}//class nodeopen<t>: Basenodegeneric <T> {}

Five, generic interface

    • Define a generic interface:
Interface Imygenericinterface<t>{}
    • An interface can define multiple type parameters, as follows:
Interface Imygenericinterface<tkey,tvalue>{}
    • A concrete class can implement a closed construction interface, as follows:
Interface Ibaseinterface<t> {}class sampleclass:ibaseinterface<string> {}//  If T is constrained, then the string type must satisfy the constraints of T

Vi. Generic mandates

A delegate can define its own type parameters. Code that references a generic delegate can specify a type parameter to create a closed constructed type, just like instantiating a generic class or calling a generic method, as shown in the following example:

 classProgram {Static voidMain (string[] args) {Del<int> m1 =Newdel<int>(Notify); M1. Invoke (1111); Del<string> m2 =Newdel<string>(Notify); M2. Invoke ("string");        Console.readkey (); }         Public Delegate voidDel<t>(T item);  Public Static voidNotify (inti) {Console.WriteLine ("{0} type is {1}", I,i.gettype ()); }         Public Static voidNotify (stringSTR) {Console.WriteLine ("{0} type is {1}", str, str. GetType ()); }           }

Operation Result:

Vii. default keywords in generic code: Defaults

One problem that arises in generic classes and generic methods is how to assign a default value to a parameterized type T when the following conditions are not known in advance:

    • T is a reference type or a value type.

    • If T is a value type, then it is numeric or structure.

Given a variable t of the parameterized type T, the statement t = NULL is valid only if T is a reference type, and the statement t = 0 is used only when T is a numeric type and not a struct. The solution is to use the default keyword, which returns null for reference types and zero for numeric types. For structs, this keyword returns each struct member initialized to zero or null, depending on whether the structure is a value type or a reference type.

namespacemygeneric{classProgram {Static voidMain (string[] args) {            Objectobj1=generictodefault<string>(); ObjectObj2 = generictodefault<int>(); ObjectObj3 = generictodefault<structdemo>();        Console.readkey (); }         Public StaticT generictodefault<t>()         {            return default(T); }    }     Public structStructdemo { Public intId {Get;Set; }  Public stringName {Get;Set; } }}

Operation Result:

A generic explanation of C #

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.