In C# there is support for Covariance in arrays from C# version 1.0 itself.
With C# 2.0 release the support for covariance and contravariance in C# has extended to delegates also.
Table of Contents
Covariance And Contravariance In C#
Delegates offer benefits such as passing methods as parameters to other methods, Single delegate for multiple functions, and callback functions.
The basic rule of thumb for a delegate is that the referenced method’s argument types and return type should match the delegate’s argument types and return types.
But this rule is a little relaxed with the covariance-contravariance support for delegates.
Covariance In C#
Covariance in C# basically means that the argument type of the method that is referenced by a delegate can have an argument type different from the delegate return type provided the argument type of the method is a subclass(derived) of the argument type of the delegate.
When you assign a method to a delegate that has a less derived return type, covariance allows you to do that.
You can use covariance to delegates, generic types, arrays, interfaces, and more.
Contravariance In C#
Contravariance in C# means that the argument type of the method that is referenced by a delegate can have an argument type different from the delegate return type provided the argument type of the delegate is a subclass(derived) of the argument type of the method.
C# Contravariance is actually applied to parameters.
The ability to have a method parameter that is of a base class provided to a delegate that expects a method parameter of a derived class is known as contravariance.
See the code sample below for more clarity.
Here below two classes defined. One derived from the other
//base class
public class Shape
{
}
//A derived class
public class Rectangle : Shape
{
}
C# Covariance Sample
//Delegate with return type as base class
public delegate Shape delgateCovariance();
//Method with return type as base class
public Shape Method1()
{
return new Shape();
}
//Method with return type as derived class
public Rectangle Method2()
{
return new Rectangle();
}
Covariance Usage is :
delegateCovariance delgate1 = Method1;
delegateCOvariance delegate2 = Method2;
C# Contravariance Sample
//Delegate with return type as a base class
public delegate void delgateContravariance(Rectangle rect);
//Method with base type as parameter
public void Method1(Shape shape
{
}
//Method with derived type as parameter
public void Method2(Rectangle rectangle)
{
}
delegateContravariance delgate1 = Method1;
delegateContravariance delegate2 = Method2;
Summary
This article covered Covariance and contravariance in C# which allow us to be flexible when dealing with class hierarchy. With covariance and contravariance, C# allows implicit reference conversions for argument types such as array types, delegate types, and generic types. Assignability is kept intact via covariance, and is inverted via contravariance. Hope you found this article useful.
Happy Coding !
[…] Covariance & Contravariance […]