The method passed to a delegate may now have greater flexibility in its return type and parameters.
1) Covariance permits assignment of a method to have a more derived RETURN TYPE than what is defined in the delegate. I.e. when a delegate returns an object, a derived type can be converted/substituted for a base/antecedent type
2) Contravariance permits assignement of a method with parameter types that are less derived than in the delegate type. I.e. when invoking a delegate, a derived parameter can be converted/substituted as a base/antecedent parameter.
note
Substitution will always make sense. Keep in mind that it is an assignment of delegate signature and the return or parameter which can be sensibly replaced by an antecedent class type. Due to the difficulty/complexity of this topic, more comments and additional code are provided to clarify co and contra variance concept beyond a minimal how to use.
how to use CoVariance
Substitution of base to decendent/derived in RETURN TYPE.
1) Create a base class, derived class from base.
2) Define a delegate RETURNING base class.
3) Create 2 methods, a) RETURNING base class and b) RETURNING derived class.
4) The delegate can accept the derived method RETURNING derived class (delegate definition defined with BASE class).
how to use ContraVariance
Substitution of defined/derived to antecedent/base in PARAMETER TYPE.
1) Create a base class, derived class from base.
2) Define a delegate with DERIVED class as PARAMETER.
3) Create 2 methods, a) with base class as PARAMETER and b) with derived class as PARAMETER.
4) The delegate can accept the method with BASE class as PARAMETER (where delegate definition is defined with DERIVED class).
ContraVariance note
A PARAMETER object as defined in delegate signature (or more derived/descendent) is required when calling an ASSIGNED delegate where BASE/antecedent class is PARAMETER! This allows a sensible defined or antecedent class substitution.