Analysis of covariant and contravariant examples of C4.0
- 2020-10-07 18:51:17
- OfStack
This article illustrates the covariant and contravariant features of C#4.0, which will help you master C#4.0 program design step by step. The specific analysis is as follows:
1. Covariant and contravariant before C#3.0
If this is the first time you've heard these two words, don't worry, they're actually quite common. The covariant and contravariant (Covariance and contravariance) in C#4.0 is a step closer, with two run-time (implicit) generic type parameter conversions. In simple terms, a covariant (Covariance) is when a type is raised from "small" to "large", such as from a subclass to a parent; Contravariant is to point to change from "big" to "small", both have different conditions and USES. The following example illustrates C#3.0's previous support for covariant and contravariant:
Code 1
public class Animal { }
public class Cat : Animal { }
public delegate Animal AniHandler(Animal a);
public static Animal AniMethod(Animal a) { return null; }
public static Cat CatMethod(Object o) { return null; }
public static void TestCovariance()
{
AniHandler handler1 = AniMethod;
AniHandler handler2 = CatMethod;// It's legal here
}
While CatMethod here does not strictly meet the delegate AniHandler's signature, it is legal for it to be used as AniHandler in covariant (Cat-) > Animal) and contravariant (object- > Animal), the delegate points to a method where the parameter passed in can be a large, broad type, and the result returned can be a smaller, more precise type (subclass), because it contains more information. When calling a method, the argument can be a "small" subclass, and the return value can be used as a "big" superclass. The following calls are valid:
object o = AniMethod(new Cat());
Well, that sounds a little confusing, but Now I'm going to try to make it clear and concise. Whether covariant or contravariant, it is intended to make a very reasonable fact true: if more type information is provided than is needed (rather than equal to it), then this is certainly possible. In the example in code 1, the AniHandler delegate requires 1 Animal as the return value, but I give it back 1 Cat. Cat contains all the features of Animal, which is certainly possible. This is covariant; At the same time, AniHandler needs 1 Animal as a parameter, so in order for the function to get more information than it needs, I can just ask for 1 object to be passed in, which is certainly possible, and that's the contravariant.
2. Covariant in C#4.0
Let's first look at how harmonious covariance occurs in 1. The covariant in C#4.0 is very similar to the loose delegate in C#3.0, and the new C# covariant feature is also present in the generic interface or in the type parameters of the generic delegate. Taking the classic Animal and Cat example again, after looking at code 1 above, since Cat CatMethod() can be used as Animal AniHandler, you have every reason to believe that the following code is also valid in C#3.0:
Code 3
delegate T THandler<T>();
static void Main(string[] args)
{
THandler<Cat> catHandler= () => new Cat();
THandler<Animal> aniHandler = catHandler;//Covariance
}
Unfortunately, you are wrong. In C#3.0, the above code will not compile and you will be told that an error has occurred!
Times have improved and the above is now supported by the compiler in C#4.0. You only need to add one out keyword before declaring the type parameter of THandler:
delegate T THandler<out T>();
Using a single keyword instead of allowing implicit conversions directly is also a type-safety concern. So when you write Covariance, you should know what Covariance is likely to happen.
3. Contravariant in C#4
We continue to use the Animal and Cat examples. In VS2008, the following code does not compile:
Code 5
delegate void THandler<T>(T t);
public static void TestContravariance()
{
THandler<Animal> aniHandler = (ani) => { };
THandler<Cat> catHandler = aniHandler;
}
In VS2010, well, no. If you put the keyword "in" in front of the type parameter T, that is, delegate void THandler < in T > (T t); Cat- can be implemented > Animal Contravariance.
4. Conclusion:
The covariant and contravariant features in C#4 make generic programming type-casting more natural, but note that the covariant and contravariant features mentioned above only work between reference types and are currently used only for generic interfaces and delegates. An T parameter can only be in or out. You cannot do this if you want to invert your delegate parameter and return covariant values (as shown in code 1).
I believe that what I have described in this paper can be used as a reference for you to better grasp the C#4.0 program design.