Object-oriented programming allows types to be substituted in some scenarios. For example, if a method returns us an Account it is fine for that method to return us a SavingsAccount instead.
This is known as Covariance and has been supported since C# 1.0 for normal types. Generic covariance brings covariance to generic types.
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 returns instances of T like an enumerable? With generic covariance we can do this!
Code
IEnumerable<Accounts> accounts = getAccounts<SavingsAccounts>();
foreach(var account in accounts)
PrintStatement(account);IEnumerable<SavingsAccounts> accounts = getAccounts<SavingsAccounts>();
foreach(var account in accounts)
PrintStatement((Account)account);This was achieved in .NET by Microsoft changing IEnumerable<T> to IEnumerable<out T>.
Notes
- The reverse of this - accepting a more specific argument rather than having a more specific one returned to you - is Generic contravariance C# 4.0