You are right, the variance of delegates is limited to reference types.
Here is a normative quote from C # language reference (lies in <Visual Studio install dir>\VC#\Specifications\1033\CSharp Language Specification.docx ), section 15.2 (my translation):
15.2 Delegate Compatibility
A method or delegate M is said to be compatible with delegate type D if the following conditions are true:
D and M same number of parameters, and each parameter in D has the same ref / out modifiers, as does the corresponding parameter in M- For each parameter that does not contain
ref / out , there is an identity conversion (§6.1.1) or an implicit reference conversion (§6.1.6) from the type of the parameter in D to the type of the corresponding parameter in M - For each
ref - / out parameter, the parameter type in D is exactly the same as in M - There is an identical or implicit reference conversion from the return type in
M to the return type in D
This means that the parameter types must either be the same (up to the difference between object and dynamic ), or the parameter type must be a reference subtype of the parameter type in D This excludes meaningful types.