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:
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;