This article describes the covariance and inversion of the new features of C# 4.0, which will help everyone further master the C# 4.0 programming design. The specific analysis is as follows:
1. Covariance and inversion before C# 3.0
If this is the first time you've heard of these two words, don't worry, they are actually very common. Covariance and inversion in C# 4.0 have been further improved, mainly two runtime (implicit) generic type parameter conversions. Simply put, the so-called covariance refers to upgrading the type from "small" to "big", such as upgrading from a subclass to a parent class; inversion refers to changing from "big" to "small", and the two have different conditions and uses. The following example demonstrates the previous support for covariance and inverter in C# 3.0:
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;//This is legal}
Although the CatMethod here does not strictly meet the signature of the delegate AniHandler, it is legal to be used as an AniHandler. Under the action of covariance (Cat->Animal) and inverse (object->Animal), in the delegate-pointed method, the passed parameters can be a large, broad type, and the returned result can be a smaller, precise type (subclass) because it contains more information. Note that this is what is said here from the method, and from the perspective of the caller using the method, it is exactly the opposite. When calling the method, the parameter can be a "small" subclass, and the return value can be used as a "big" parent class, such as the following call is legal:
object o = AniMethod(new Cat());
Haha, it sounds a little dizzy, now I want to try to express the problem concisely. Whether it is covariance or inversion, it is intended to make the fact that this is certainly OK if more type information is provided than the type information required (rather than equal). In the example of code 1, the AniHandler delegate requires an Animal as the return value, but I return it a Cat, which contains all the characteristics of Animal, which is of course OK, which is covariance; at the same time, the AniHandler requires an Animal as a parameter. In order to get more information from the function than required, I can only ask for an object to be passed in, which is of course OK, which is inverse.
2. Covariance in C# 4.0
Let’s first look at how harmonious covariance occurs. The covariance in C# 4.0 is very similar to the loose delegation in C# 3.0. The new C# covariance feature is also reflected in the type parameters of the generic interface or generic delegation. Take the classic Animal and Cat as examples. After you have looked at the above code 1, since Cat CatMethod() can be used as Animal AniHandler, then you have every reason to believe that the following code is also legal 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 cannot be compiled and you will be told that an error has occurred!
The times have improved, and the compiler in C# 4.0 now supports the above writing method. You just need to add an out keyword before declaring the type parameter of THandler:
delegate T THandler<out T>();
Using a keyword alone instead of allowing implicit conversions directly is also a type safety consideration. So when you write out, you should know the possible Covariance.
3. Inversion in C#4
We continue to use the examples of Animal and Cat, in VS2008, the following code cannot be compiled:
Code 5
delegate void THandler<T>(T t); public static void TestContravariance() { THandler<Animal> aniHandler = (ani) => { }; THandler<Cat> catHandler = aniHandler; }
And in VS2010, uh, it's also not possible. Haha, it's actually a little bit short. If you add the keyword "in" to the type parameter T, that is, delegate void THandler<in T>(T t); to realize the Contravariance of Cat->Animal.
4. Summary:
The covariance and inversion in C#4 make type conversion more natural during generic programming, but it should be noted that the covariance and inversion mentioned above only act between reference types, and currently only use generic interfaces and delegates. A T parameter can only be in or out. If you want to invert your delegate parameter and want to return value covariance (as shown in code 1), you cannot do it.
I believe that the description in this article will have a certain reference effect for everyone to better master the C# 4.0 programming design.