Generic Type in c,

Source: Internet
Author: User

Generic Type in c,

This article mainly talks about generics in c #, because generics play an important role in c # and play a key role in writing highly readable and high-performance code. When I often see that my team's code contains a large number of non-generic sets, implicit packing and unpacking operations, I suggest that they fill in the generic basics.

1. What is generic

    • Generic is a very important new feature in c #2. It enhances code readability and transfers a large number of security checks from the execution period to the compilation period, thus improving code security and performance. Basically, generics implement parameterization of types and methods.

2. Why should I use generic and generic solutions?

Let's take a look at the following code (the code is just to demonstrate generics and has no practical significance) to see what's wrong?

1 class Program 2 {3 static void Main (string [] args) 4 {5 ArrayList array = new ArrayList (); 6 array. add (1); 7 array. add (2); 8 array. add (3); 9 ArrayList resultArray = NumberSqrt (array); 10 foreach (var item in resultArray) 11 {12 Console. writeLine (item); 13} 14} 15 public static ArrayList NumberSqrt (ArrayList array) 16 {17 ArrayList sqrtArray = new ArrayList (); 18 foreach (var item in array) 19 {20 sqrtArray. add (Math. sqrt (double) (int) item); 21} 22 return sqrtArray; 23 24} 25}View Code
    • First, ArrayList is a non-generic set, and the required parameter is object. If I assemble other types into the set, errors cannot be judged during compilation (for example, if I assemble a string, it can be compiled successfully ).
    • Because ArrayList requires an object, you will perform implicit packing when assembling the value type into the set. When using the data in the set, you need to perform the unpacking operation. This affects the application performance. (For more information about Value Type Packing, see reference type and value type in c ).
    • The code can be poorly readable and cannot understand the type of ArrayList assembly.

Let's take a look at how generics solve these problems:

1 class Program 2 {3 static void Main (string [] args) 4 {5 List <double> array = new List <double> (); 6 array. add (1); 7 array. add (2); 8 array. add (3); 9 List <double> resultArray = NumberSqrt (array); 10 foreach (var item in resultArray) 11 {12 Console. writeLine (item); 13} 14} 15 public static List <double> NumberSqrt (List <double> array) 16 {17 List <double> sqrtArray = new List <double> (); 18 foreach (var item in array) 19 {20 sqrtArray. add (Math. sqrt (double) (int) item); 21} 22 return sqrtArray; 23 24} 25 26}View Code
    • Because List <double> can only assemble double types, the compiler reports an error when assembling other types to improve code security.
    • Because List <double> can only be used to assemble double types, this avoids implicit packing and unpacking operations by the compiler and improves application performance.
    • You can see the type of the set to be assembled at a glance to improve the readability of the Code.
    • The NumberSqrt method is useless here. If you want to write an algorithm and change NumberSqrt to a generic method: NumberSqrt <T> (such as a sorting algorithm), you can reuse the algorithm.

3. How to Use generics: syntax and rules

What is generic and why it is generic? Let's talk about how to use generic

    • Generic Syntax: generics mainly include generic methods (for example, static void Swap <T> (ref T lhs, ref T rhs) and generic interfaces (for example: public interface IEnumerable <out T>: IEnumerable), generic delegation (for example, public delegate void Action <in T> (T obj );)
    • Many generic interface definitions are built in FCL. collections. generic), in order to make generics work normally, Microsoft developers will do the following work,
      • Create new IL commands to recognize type parameters.
      • Change the metadata format to recognize generic parameters and generic methods.
    • Open Type and closed type: When a generic type does not specify the actual data type, it is called an open type, such as List <T>, no instance of this type can be created for any open type. For example, if the following code is run, an error is returned: handled exception: System. argumentException: the instance of leleapplication2.demo '1 [T] cannot be created because of Type. containsGenericParameters is True.
1 public class Demo <T >{} 2 class Program 3 {4 static void Main (string [] args) 5 {6 object o = null; 7 Type t = typeof (Demo <>); 8 o = Activator. createInstance (t); 9} 10}View Code

If all types of arguments of the generic type pass actual data types, the type is called closed type. CLR allows the construction of closed type instances.

    • Generic Type and inheritance: a generic type is only a special type, so it can be derived from any other type. For example, if List <T> is derived from an object, List <String> is also derived from the object. In other words, there is no relationship between the designation of type arguments and the hierarchy of inheritance-understanding this helps you determine whether or not those transformations can be performed and what transformations cannot be performed.
    • How does the compiler solve the "Code explosion" problem: when using a generic type or method, Clr gets the IL code and replaces it with the specified type of real parameter. If Clr generates different local code for each different type/method combination, it may increase the working set of the application and affect the performance. We call this phenomenon "code explosion". Then how does the compiler solve this problem? The compiler considers all arguments of the reference type to be identical, so the code can be shared (why? Because all the arguments or variables of the reference type actually point to the pointer of the object on the stack, and all the object pointers are operated in the same way ). However, if a real parameter of a type is a value type, CLR must generate local code for that value type. This is an indefinite value type.
    • Generic interface: Why should I use a generic interface? Every time you try to use a non-generic interface to operate a value type, it will be boxed, thus losing the type security during compilation. Therefore, CLR provides support for generic interfaces. Here is an example: 1 // Abstract: 2 // simple iteration on a generic set is supported. 3 // 4 // type parameter: 5 // T: 6 // type of the object to be enumerated. 7 public interface IEnumerator <out T>: IDisposable, IEnumerator 8 {9 // Abstract: 10 // gets the elements at the current position of the enumeration number in the set. 11 // 12 // return result: 13 // The element in the set at the current position of the enumerative number. 14 T Current {get;} 15}View Code
    • Generic delegation: CLR must support generic delegation to ensure that all types of objects can be passed to a callback method in a type-safe manner, it also ensures that no packing is performed when a value type instance is passed to a callback method.
    • Generic method: when defining a generic class, structure, or interface, any method defined in these types can reference A type parameter specified by the type. The type parameter can be used as a method parameter/return value, or as a local variable inside the method. Here is an example: 1 class Program 2 {3 static void Main (string [] args) 4 {5 MyClass <string> myclass = new MyClass <string> (); 6 myclass. showInfo ("myClass"); 7} 8} 9 10 class MyClass <Ta> 11 {12 public void ShowInfo (Ta a) 13 {14 Type t = typeof (Ta ); 15 Console. writeLine (t. fullName + "non-generic method"); 16} 17 public void ShowInfo <Ta> (Ta a) 18 {19 Type t = typeof (Ta); 20 Console. writeLine (t. fullName + "generic method"); 21} 22 public void ShowInfo <Tb> (Ta a, Tb B) 23 {24 Type t = typeof (Tb); 25 Console. writeLine (t. fullName); 26} 27}View Code

      Type inference of generic methods: the c # syntax contains a large number of "<" and ">" symbols, which reduces the readability and maintainability of the Code. to change this situation, c # The Compiler supports calling a method.Type inference.For example, the following code: myclass. ShowInfo ("myClass", myclass); will call ShowInfo <string> (string a, string B );

    • Verifiable and constraint: the compiler analyzes generic code when compiling it to ensure that the Code applies to any types that are existing or may be defined in the future. See the following method: 1 public static Boolean MethodTakingAnyType <T> (T o) {2 T temp = o; 3 Console. writeLine (o. toString (); 4 Boolean B = temp. equals (o); 5 return B; 6}View Code

      There is a temporary variable temp in this method. The method can be used to assign values to variables and call Methods twice, regardless of whether T is a value type, a reference type, an interface type, or a delegate type. This method applies to existing and any types that may be defined in the future. For example, let's look at the following method:

      1 public static T MethodTakingAnyType <T> (T o1, T o2) {2 if (o1.CompareTo (o2) <0) 3 {4 return o1; 5} 6 else {7 return o2; 8} 9}View Code

      The following error is reported during compilation (error CS0117: "T" does not contain the definition of "CompareTo"), because not all types provide the CompareTo method. So under what circumstances should T be of what type? Fortunately, the compiler and CLR supportConstraintsCan be used to make generics really useful!

      • Constraint Syntax: see where1 public static Boolean MethodTakingAnyType after the method name <T> (T o) where T: struct2 {3 T temp = o; 4 Console. writeLine (o. toString (); 5 Boolean B = temp. equals (o); 6 return B; 7}View Code

        The where keyword of c # Tells the compiler that any type specified for T must be a value type. Therefore, when you specify another type for T, the compiler will report an error. For example, if you specify a string type (MethodTakingAnyType <string> ("");) it will report error 1 type "string" must be of a type that cannot be null value to be used as a generic type or Method

      • Main constraint: zero or one major constraint (that is, the first constraint) can be specified for a type parameter ). The main constraint can be a reference type. It identifies an unsealed class and cannot specify the following special types: System. object; System. array; System. delegate; System. multicastDelegate; System. valueType; System. enum;
      • Secondary constraints: zero or multiple secondary constraints can be specified for a type parameter. A secondary constraint is an interface type. When an interface type constraint is specified, it indicates that the compiler-type real parameters must implement this interface. There is also a secondary constraint calledType parameter constraints,It is also called a bare type constraint. See the following code: 1 public static Boolean MethodTakingAnyType <T, TBase> (T o) where T: TBase2 {3 T temp = o; 4 Console. writeLine (o. toString (); 5 Boolean B = temp. equals (o); 6 return B; 7}View Code

        T-type parameters are restricted by the TBase Type singular values. That is to say, all T-type parameters must be compatible with the real-type parameters specified by TBase.

      • Constructor constraints: zero or one constructor constraint can be specified for a type parameter. Specifying a constructor constraint is equivalent to telling the compiler that a specified type of real parameter must implement a public parameter-free constructor. See the following code: 1 public static Boolean MethodTakingAnyType <T, TBase> (T o) where T: new () 2 {3 T temp = o; 4 Console. writeLine (o. toString (); 5 Boolean B = temp. equals (o); 6 return B; 7}View Code
      • Other verifiable problems: 1. Transformation of generic variables. The following type compilation error occurs because T may be of any type and cannot be guaranteed to be successful! 1 public static void MethodTakingAnyType <T, TBase> (T o) 2 {3 int x = (int) o; 4 string s = (string) o; 5}View Code

        2. Set a generic type variable to the default value: o = default (T). In this way, whether T is a value type or a reference type, if T is of the reference type, it is set to null. If T is of the value type, the default value is 0;

        3. Compare a generic type variable with Null: Use = OR =! It is legal to compare a generic type variable with null. However, if T is of the value type, o will never be null. view the following code: 1 public static void MethodTakingAnyType <T, TBase> (T o) 2 {3 if (o = null) {4 // do something5} 6}View Code

        4. Compare two generic variables: If T is a value type, the following code is invalid.

        1 public static void MethodTakingAnyType <T> (T o1, T o2) 2 {3 if (o1 = o2) {4 5} 6}View Code

4. Precautions for Using Generics

    • Generics do not support Covariance
    • Lack of operator constraints or numerical Constraints
    • Lack of generic attributes, indexer and other member types

 

Related Article

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.