About

I am a software developer in Seattle, building a new AI software company.

Ads

May 2008

Sun Mon Tue Wed Thu Fri Sat
        1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31

Ads


« E-books | Main | C# Changes »

June 06, 2004

Covariance and Contravariance for Delegates

According to the Whidbey help, contravariance of delegate parameters and covariance of return types may be supported for delegates in the Whidbey release. Variance was mentioned in a prior Don Box post. In .NET 1.1, delegates could only be created with methods whose arguments strictly matched the signature of that delegate. Now, it appears the requirements may been relaxed to allow methods with compatible signatures (though I haven't actually noticed any changes to the C# spec to reflect this).

Note the help documentation is still incomplete and the feature and its availability is subject to change. I have yet to test this out on the May CTP as I have had repeated installation failures, but I have been wishing for this feature.

Suppose we have three classes.

public class MyBase
{
}

public class MyClass : MyBase { }
public class MyDerived : MyClass { }

and a delegate defined as follows:

public delegate MyClass MyDelegate(MyClass arg);

Covariance
Covariance of return values allows a delegate of type, say D, to wrap a method whose return value is of a type, which derives from or equals the return value type of D.

For example, MyDelegate may match the following as a result of covariance:

MyDerived Foo(MyClass arg);

Note that the MyDelegate will not match Foo if the return type was that of a base class, because that would not be compatible with the original signature of the delegate.

Contravariance
Contravariance of methods parameters allows a delegate of type D to wrap a method whose parameters have a type, which is either a base class of or the same class of the type of the corresponding parameter in the signature of D.

For example, MyDelegate may match the following as a result of contravariance:

MyClass Foo(MyBase arg);

Note that the MyDelegate will not match Foo if the parameters are of derived types instead of base types, for compatibility reasons as well.

Comments

Is the following scenario also considered covariance ... and do you know if it will be supported in the whidbey release?

If the delegate is ...

public delegate MyClass MyDelegate(MyClass arg);

Is

MyClass Foo(MyDerived arg);

also covariance and supported?

It's still there in B2

dakotahnorth - no, that's what he says in the last paragraph.

Think of the actual code - somewhere (probably in the defining class), you'll have some code that calls an instance of the delegate, passing a MyClass argument.

If you've created the delegate instance around a method a that expects a MyDerived parameter, a MyClass argument to that method could be a MyDerived, but it could equally well be a MyDerived2 (which subclasses MyClass). If you're relying on members of MyDerived (which is why you'd specify that type), you aren't going to find them on an instance of MyClass or MyDerived2.

If the code compiled successfully, you'd get an invalid cast exception at runtime. So the compiler says "No, that's an implicit downcast, which isn't safe."

The comments to this entry are closed.