“Covariance allows you to encapsulate a method with a return type that is directly or indirectly derived from the delegate’s return type.”
You could assign a delegate with a method that returns a type (sub type) that is derived (directly or indirectly) from the delegate’s defined return type; this is known as Covariance.
I.e., if a delegate is defined to return a Person type, then you could use this delegate to assign a method that returns a Manager type, if Manager type is derived from Person type.
“Contravariance allows you to encapsulate a method with a parameter that is of a type from which the declared parameter is directly or indirectly derived.”
You could define a delegate method with signature in which one or more of the parameters is derived (sub type) from the type defined by the delegate. This is known as Contravariance.
I.e., if the delegate is defined to accept a method whose input parameter is of Manager type, then you could use this delegate to assign to a method that passes in a Person type (base type) as a parameter, if Manager type derives from Person type.
Thus, using Contravariance, you could pass in an object of the base type as a parameter where an object of the derived type is expected.
Example: Using covariance and contravariance
using System;using System.Collections.Generic;using System.Text;public class Person{ public virtual Person ReturnsPerson() { Console.WriteLine(“Returning a Person type”); return this; }}public class Manager : Person{ public Manager ReturnsManager() { Console.WriteLine(“Returning a Manager type”); return this; }}class Program{ public delegate Person covariantDelegate( ); public delegate void contravariantDelegate(Manager manager); private static void MethodThatTakesAPerson(Person person) { Console.WriteLine(“Method That Takes A Person type”); } private static void MethodThatTakesAManager(Manager manager) { Console.WriteLine(“Method That Takes A Manager type”); } static void Main(string[] args) { Person person = new Person(); Manager manager = new Manager(); covariantDelegate myCovariantDelegate = new covariantDelegate(person.ReturnsPerson); myCovariantDelegate(); myCovariantDelegate = new covariantDelegate(manager.ReturnsManager); myCovariantDelegate(); contravariantDelegate myContravariantDelegate = new contravariantDelegate(MethodThatTakesAManager); myContravariantDelegate(manager); myContravariantDelegate = new contravariantDelegate(MethodThatTakesAPerson); myContravariantDelegate(manager); }}Output:Returning a PersonReturning a ManagerMethod That Takes A ManagerMethod That Takes A Person
Hope this helps,