C# Language Variant delegates


Delegates may have variant type parameters.

delegate void Action<in T>(T t);    // T is an input
delegate T Func<out T>();           // T is an output
delegate T2 Func<in T1, out T2>();  // T1 is an input, T2 is an output

This follows from the Liskov Substitution Principle, which states (among other things) that a method D can be considered more derived than a method B if:

  • D has an equal or more derived return type than B
  • D has equal or more general corresponding parameter types than B

Therefore the following assignments are all type safe:

Func<object, string> original = SomeMethod;
Func<object, object> d1 = original;
Func<string, string> d2 = original;
Func<string, object> d3 = original;