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