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).