Correct - you don't understand covariance correctly - yet :) Your code would work if you had the same types but as return values, like this:
public delegate object MyDelegate()
public class MyClass
{
public MyClass()
{
_delegate = MyMethod;
}
private MyDelegate _delegate;
public SomeObject MyMethod() { return null; }
}
That would demonstrate covariance. Alternatively, you can keep it as parameters but switch the types around:
public delegate void MyDelegate(SomeObject obj)
public class MyClass
{
public MyClass()
{
_delegate = MyMethod;
}
private MyDelegate _delegate;
public void MyMethod(object obj) {}
}
This now demonstrates contravariance.
My rule of thumb is to ask myself, "given the delegate, what could I do with it? If I can pass in an argument which would break the method, the conversion should have failed. If the method can return something which would break the caller, the conversion should have failed."
In your code, you could have called:
_delegate(new object());
At that point, poor MyMethod
has a parameter which is meant to be of type SomeObject
, but is actually of type object
. This would be a Very Bad Thing, so the compiler stops it from happening.
Does that all make more sense?