Generic covariance and contravariance allow you to declare a generic interface or generic delegate whose variables can be initialized using expressions whose type argument can be more/less derived than the type argument of the variable.
In other words, without covariance and contravariance we can do this:
Code:
delegate void D<T>();
interface I<T> { };
class C<T> : I<T> { };
static void Main(string[] args)
{
I<StringBuilder> i = new C<StringBuilder>();
D<StringBuilder> d = new D<StringBuilder>(() => { });
Console.Read();
}
But with generic covariance/contravariance we can also do this:
Code:
delegate void D<in T>();
interface I<out T> { };
class C<T> : I<T> { };
static void Main(string[] args)
{
I<object> i = new C<StringBuilder>();
D<StringBuilder> d = new D<object>(() => { });
Console.Read();
}
That said, can someone help me think of an example where generic covariance/contravariance is necessary or at least useful?