Object-oriented programming allows types to be substituted in some scenarios. For example, if a method takes a Account it is fine to pass in an instance of the subclass SavingsAccount.
This is known as Contravariance and has been supported since C# 1.0. Generic contravariance brings this to generics!
Let us consider IList<T>. We can never assign anything implementing this interface to IList<SubOfT> because it both accepts arguments of T (Add) and returns T (for Get). No type except T can be both a subclass and a superclass.
But what about a interface that only accepts T and does something with it like a message sender? Using generic contravariance solves this problem.
Code
C#
ISender<MyMessage> sender = getSender(); // Is actually Sender<Message>
sender.Send(new MyMessage());
...
interface ISender<out T> { ... }C#
// Can't constrain this to MyMessage without creating a new sender
ISender<Message> sender = getSender(); // Is actually Sender<Message>
sender.Send(new MyMessage());
...
interface ISender<T> { ... }Notes
- It's easier to start by understanding Generic covariance C# 4.0 first