[C # advanced series] 11 generic,

Source: Internet
Author: User

[C # advanced series] 11 generic,

Generic is a special mechanism provided by CLR and programming languages. It is used to meet the requirement of "algorithm reuse ".

It can be imagined that a policy mode with different data types of only the parameters of the operation can be converted into a function using generics.

The following are their advantages:

  • Type Security
    • When a specific data type is applied to a generic algorithm, if this type is not compatible, a compilation error or an exception is reported.
  • Clearer code
    • Reduces forced conversions and simplifies code
  • Better performance
    • Using Generics can effectively avoid packing and unpacking, and do not need to verify whether the type is safe during forced conversion. Both of these two aspects effectively improve the Code performance.

This is why List <T> has eliminated ArrayList, especially when performing value type operations, the gap is large because there are too many binning cases.

Convention: Generic parameters must either start with T or start with uppercase or lowercase T, for example, List <T>.

Generic in FCL

The System. Collections. Generic and System. Collections. ObjectModel Namespaces provide multiple Generic collection classes and interfaces.

The System. Collections. Concurrent namespace provides thread-safe generic collection classes.

The System. Array class provides a large number of static generic methods.

Basic Structure of generics

. Net 2.0 is generic.

  • Open and closed types
    • Previously, we mentioned that CLR will create type objects for various types, and a new generic class TroyList <T> will also create a type object. We will name the type with generic parametersOpen type.
      • An open instance cannot be constructed.
    • The generic type that specifies the generic type parameter is calledClosed TypeFor example, TroyList <int>.
      • You can construct a closed-type instance.
      • If TroyList <T> defines static fields or methods, TroyList <int> and TroyList <string> are not shared because they are actually two different types of objects.
  • Inheritance of generic types
    • After using the generic type and specifying the type arguments, it is actually a new closed type. The new type object is derived from the type derived from the generic type. That is, if List <T> is derived from the Object, List <int> is derived from the Object.
  • Optimization of code explosion
    • Here you may think that an open type actually has multiple closed types. For example, a List <T> has multiple closed types, such as List <int> and List <string>. It is actually N-plus type objects that generate N-plus repeated code, so this is called code explosion.
    • Optimization:
      • Two different assemblies use the same closed type, which is changed only once by the JIT compiler.
      • CLR considers that all closed types using reference types as type arguments are identical, so code can be shared. That is to say, the compiled code of the List <String> and List <Stream> methods can be generic. Because the size of different reference types of the operation is the same.

Real parameters of the Delegate and interface inverters and the wildcard type of coordination

Each generic type parameter of the generic delegate and interface can be marked as a covariable and an inverter. This function can be used to convert the delegate and interface of the same type but with different real parameters. (You can refer to the following if you do not understand it)

  • Invariant
    • This means that parameters of the generic type cannot be changed.
  • Inverter quantity
    • This means that the generic type parameter can be changed from a class to its derived class. The in mark indicates that parameters of the generic type of the inverter can only appear at the input position.
  • Covariant
    • This means that the generic type parameter can be changed from a class to its base class. With the out flag, the generic type parameters of the covariable can only appear in the output position.

For example

Public class base class {} public class derived class: base class {} public class Test {public delegate TResult MyFunc <in T1, out TResult, T2> (T1 a, T2 B ); // The first is the inverter quantity, the second is the covariable, and the third is the invariant void show () {MyFunc <base class, base class, base class> fn1 = null; // The following comments are my own comprehension methods, just for convenience. MyFunc <derived class, base class, base class> fn2 = fn1; // MyFunc <derived class, derived class, base Class> fn2 = fn1; Conversion error MyFunc <base class, Object, base class> fn3 = fn1; // MyFunc <Object, Object, base class> fn3 = fn1; conversion error MyFunc <derived class, Object, base class> fn4 = fn1 ;}}

It is still very difficult. In fact, it doesn't matter if you don't understand it. If you cannot convert it, the compiler will naturally prompt. You can understand this. We also recommend that you use int and out to specify the type variable of the generic delegate. In more cases, we will use the built-in generic delegate Action and Func. The parameters of these two generic delegates are both in and out.

Type inference for generic methods

Void Go () {String s1 = "213"; Object s2 = "123"; Show (s1, s2 ); // if the Show <T> T method is not specified, it is called type inference. type inference is inferred by the input variable s1 and variable s2 variable types, rather than the actual type. Because the two variables have different types, function compilation fails. } Void Show <T> (T a, T B ){}

Constraints

Generic constraints are very interesting.

void Show<T>(T a,T b) where T :IList { }

For example, the above function restricts the input type T to implement the IList interface.

Restrictions can be used to restrict the input types. However, because of this constraint, we can use various methods of IList to ensure that all input types implement the IList interface.

Constraint type:

  • Main constraints
    • The main constraint can be a reference type that represents a non-seal class. (You can specify 0 to 1 major constraint)
    • The two special constraints are class and struct, respectively. The parameters passed in are reference type and value type. (In special cases, struct cannot constrain Nullable <T>)
    • Constraints cannot specify the following special reference types: Object, Array, Delegate, MulticastDelegate, ValueType, Enum, or Void.
  • Secondary Constraints
    • Secondary constraints indicate the interface type. (You can specify 0 to multiple secondary constraints)
    • A special secondary constraint, that is, one of the two specified generic type parameters inherits the other, for example, where T2: T1.
  • Constructor Constraints
    • The constructor restricts the real parameters of the type. It must be a non-Abstract type that implements the common no-argument constructor. (0 to 1 constructor constraints can be specified)
    • All value types provide the public parameter-free constructor implicitly. Therefore, the use of both struct and new () constraints is considered redundant and an error is returned.

Verifiable

In the following cases, an error is reported because the Code cannot be verified as legal:

  • Conversion of generic Variables
    • Cause: the variable of the generic type T cannot be converted to another type. Because T may be any variable, the conversion may fail.
    • Void Show <T> (T obj) {string a = (string) obj; // error}
    • Solution:
      Void Show <T> (T obj) {string a = obj as string; // for string, the ToString method may be more appropriate here}

      The value type can be forcibly converted to an object before being converted to a specific value type. However, I think such code still needs to be packed out of the box. You may consider modifying the algorithm.

  • Set the generic type variable to the default value.
    • Cause: Because T can be a value type or a reference type, it is impossible to set a default value type or reference type.
    • Solution: Add constraints or use default (T) as the default value.
  • Comparison between two generic Variables
    • Cause: an error is returned if the = Operator is overloaded for non-primitive value types.
    • Solution: Consider the constraints as class or Equals. (Note: it is possible that Equals is overwritten, so it is not determined whether to determine the identity or equality)
  • Use generic variables as operands
    • Cause: an error is reported if the operator is overloaded unless the value type of the non-primitive type is used.
    • Solution: Reflection, operator overload, or dynamic. (Performance is affected. I usually use dynamic)

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.