Covariance and Contravariance in Delegates explained

When you call a method, you can supply arguments that have more specific types than the parameters of that method. This is ordinary polymorphic behavior. For exactly the same reason, a delegate can have more specific parameter types than its method target. This is called contravariance.

Example

delegate void Method1(string _var);

    class Temp

    {

        static void Main()

        {

            Method1 M1 = new Method1(TempMethod);

            M1("abc");

        }

        static void TempMethod(object str)

        {

            Console.WriteLine(str); // abc

        }

    }

If you call a method, you may get back a type that is more specific than what you asked for. This is ordinary polymorphic behavior. For exactly the same reason, the return type of a delegate can be less specific than the return type of its target method. This is called covariance.

Example
 

delegate object Method2();

    class Temp

    {

        static void Main()

        {

            Method2 _method2 = new Method2(GetVal);

            object res = _method2();

            Console.WriteLine(res); // abc

        }

        static string GetVal() { return "abc"; }

    }

 
Conclusion

Contravariance is Method parameter compatibility (ie. arguments in method signature) covariance is Method Return type compatibility (ie. return type in method signature).
 

Next Recommended Reading Delegates and Types of Delegates