.NET Core CSharp generic primary articles 1-8, and the inverter covariant

.NET Core CSharp primary articles 1-8

This section is a generic

Why generics

Generics is a very interesting thing, he appeared to reduce the rate of code reuse has been a great help. For example, we encountered two modules is very similar, but one is data processing int, the other is processing string data, or other custom data types, but we have no recourse but were written multiple methods for each data processing type, the parameter type because different methods. Is there a way, incoming general in the method of data types, so you can not merge the code yet?

About Generics

In our C #, when using generic programming element to allow you to delay writing classes or methods of data type specification until it is actually used in the program. In other words, it allows you to write generic class or method can work with any data type. Defining Generic is very simple to use after the class or function name To as a placeholder, the T can be replaced by other letters instead.

Note: The properties and the indexer can not specify their generic parameters, they can only be relevant to the use of generic parameters defined in the class operation.
You can get generics on some methods defined by the following example.

It is noteworthy that generics are dynamically change at runtime, not at compile time.

Generic functions and generic class

Generic functions and generic class used in basically the same, but the scope of the definitions are not the same. For the generic class, the whole range of generic class, is a generic function within the function.

Such as this example

class A<T>
{
    public T getSomething<X>(X m,T n)
    {
        return n;
    }
    public static U test<U>(U x)
    {
        return x;
    }
}
// 实例泛型类必须指定类型
A<string> a = new A<string>()
//泛型推断
A.test<int>(1);//原式
A.test(1);//推断

In calling a generic function, there is a syntactic sugar, it is a generic type inference. It is very easy to understand, C # compiler is smart enough, it can according to your type of parameters passed, calling gettype method type inference. So you can not explicitly specify the type of the generic function.
The same rule applies to the static type inference and instance methods. The compiler can infer the type of argument to the method based on the parameters; or the constraints can not only return values inferred type parameter. Accordingly, discomfort does not have the type inference for parameters. Type inference occurs at compile time, after the compiler tries to resolve overloaded method signatures. Type inference logic compiler generic methods all share the same name applied. The heavy-duty solution step, the compiler includes a method in which the generic type inference success only.

Range of generics is the inclusion relation. Included in the generic class of generic functions are free to access generic generic class, but the class can not access the specified generic generic function.

Generic constraints

If we use the generic, then there must be a problem that is faced by a permissions problem. E.g. class A , Suppose I want certain types can not be passed as a generic, then we should use our generic constraints.
Example generic constraints using the following:

class A : T where T:class
{
    
}

Generic constraints usually have the following categories:

  • where T: struct: type parameter must be a value type. Except Nullable can be specified Any value other than the type.
  • where T: class type parameter must be a reference type. This constraint also applies to any class, interface, or delegate array type.
  • where T: unmanaged type parameter can not be a reference type, and any nested level can not contain any reference type members.
  • where T: new () type parameter must have a public no argument constructor. When used in conjunction with other constraints, new () constraint must be specified last.
  • where T: <base class name> class type parameter must be specified group derived from a base class, or specified.
  • where T: <Interface name> Type parameter must be specified interface or implement the specified interface. Constraints can specify multiple interfaces. Constraints interface may also be generic.
  • where T: T type parameter U is supplied parameters must be provided from the U of U to provide parameters or derived.

Some constraints are mutually exclusive. All value types must have no accessible constructor parameter. struct constraint comprises new () constraint, and the new () constraint can not be combined with the struct constraint. Constraints include unmanaged struct constraint. unmanaged struct constraint or not be combined with new () constraint. We can use the time to pay attention.

You may specify more placeholders, and constrained to them individually, such as:

class A<T,U> 
        where T:struct
        where U:class

You can even generic self-restraint, for example:

class A<T,U,K> 
        where T:struct
        where U:K

Covariance and

These three terms from mathematics and physics, many beginners are difficult to understand these terms. But in fact in C #, these words are used in the binding between the type and the type of label. Variability is a type-safe way, as an object to another object to use. If you can not replace one type to another type, this type it is called: unchanged.

Covariant

If a return type can be replaced by a derived type, then this type of support is covariant. Straightforward to say, covariance is a reasonable change, such as cats -> animals, this did not seem a problem. This is the covariance, from small to large.

E.g:

// Cat:Animal
//这种变化毫无问题
Cat c = new Cat();
Animal a = c;
//报错,因为List<Cat>不继承于List<Animal>
List<Cat> d = new List<Cat>();
List<Animal> = d;

For generic parameters, we can use the function parameters speak before we encountered in, out keywords. In representative of the input, the inverter is embodied, Out represents the output, represents the covariant. Out of output for something, not against his natural input operation, he can only return as a result, so it will not be modified. So when the implicit conversion, the compiler considers the conversion is secure (the return value is unchanged).

E.g

    IEnumerable<Cat> c = new List<Cat>();

    IEnumerable<Animal> a = c;

Many people may not not well understood these terms from physics and mathematics. We do not need to know their mathematical definition, but at least should be able to distinguish between covariant and inverter. The word actually comes from the binding between type and type. We begin to understand from the array. In fact, the type of array binding is between one kind and specific types. Array type Int32 [] corresponding to the original type Int32. Any type T has its corresponding array type T []. So our problem comes, if there is a safe implicit conversion between two types of T and U, then the corresponding array type T [] U and whether there is such a conversion between [] it? This involves the existence of the type of the original cast on the ability to map their array type, this ability is called "Variability (Variance)". In the .NET world, the only allowed variability type conversion is brought about by inheritance "sub-class reference -> Parent class reference" conversion. For example, the type is inherited from Object type String, so any reference to a String can be converted safely to Object reference. We found String [] array reference also inherited this type of conversion capability, it can be converted into Object [] array type of reference, an array of this same type as the original transducing direction referred to the variability of the covariant

Inverter

The inverter is precisely the opposite of covariance, referring to the type of inverter is converted to a smaller derived class, it is clear that there may not be safe, because there may result in loss of data. Use inverter method in C # using the In keyword, which means that this parameter can be returned as a return value, then we may make changes to the parameters passed, so it is possible to use a cast is illegal .
E.g:

public interface IMyList<in T>
{
    T GetElement();
    void ChangeT(T t);
}

public class MyList<T> : IMyList<T>
{
    public T GetElement()
    {
        return default(T);
    }
    public void ChangeT(T t)
    {
        //Change T
    }
}

This code will not compile because GetElement T is returned, which obviously does not meet the definition of an inverter. The only parameter input of the inverter output is not allowed.

For the practice of the inverter, you can go to see the IList implementation under the IEnumerable interface. Both interfaces reflects well in the inverter with the set of covariance.

(Lack of illustration, subsequent fill)

to sum up

For generics, and not too many clever but useless at all, because that is a generic appearance has a clever but useless. The most common place is generic generic array. And C # will be used for an array of indeterminate type and size of a very useful class called List class, we will conduct a detailed introduction in the mid-chapter.

If my article help you, please have your github .NET Core Guide project helped me a star, a concern and recommendation in the garden midpoint blog.

Github

BiliBili Home

WarrenRyan's Blog

Blog Park

Guess you like

Origin www.cnblogs.com/WarrenRyan/p/11261114.html