C# 4.0: Covariance And Contravariance In Generics Made Easy
In my last post, I went through what is variance in .NET 4.0 and C# 4.0 in a rather theoretical way.
Now, I’m going to try to make it a bit more down to earth.
Given:
class Base { } class Derived : Base { }
Trace.Assert(typeof(Base).IsClass && typeof(Derived).IsClass && typeof(Base).IsGreaterOrEqualTo(typeof(Derived)));
-
Covariance
interface ICovariantIn<out T> { }
Trace.Assert(typeof(ICovariantIn<Base>).IsGreaterOrEqualTo(typeof(ICovariantIn<Derived>)));
-
Contravariance
interface IContravariantIn<in T> { }
Trace.Assert(typeof(IContravariantIn<Derived>).IsGreaterOrEqualTo(typeof(IContravariantIn<Base>)));
-
Invariance
interface IInvariantIn<T> { }
Trace.Assert(!typeof(IInvariantIn<Base>).IsGreaterOrEqualTo(typeof(IInvariantIn<Derived>)) && !typeof(IInvariantIn<Derived>).IsGreaterOrEqualTo(typeof(IInvariantIn<Base>)));
Where:
public static class TypeExtensions { public static bool IsGreaterOrEqualTo(this Type self, Type other) { return self.IsAssignableFrom(other); } }