Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Contravariant Delegates Value Types

Can anyone shed light on why contravariance does not work with C# value types?

The below does not work

private delegate Asset AssetDelegate(int m);

internal string DoMe()
{
    AssetDelegate aw = new AssetDelegate(DelegateMethod);
    aw(32);
    return "Class1";
}

private static House DelegateMethod(object m)
{
    return null;
}
like image 298
Jack Kada Avatar asked Jun 09 '10 08:06

Jack Kada


People also ask

What is the difference between covariance and contravariance in delegates?

Covariance permits a method to have return type that is more derived than that defined in the delegate. Contravariance permits a method that has parameter types that are less derived than those in the delegate type.

Can delegates be used with generic types?

Delegates defined within a generic class can use the generic class type parameters in the same way that class methods do. Generic delegates are especially useful in defining events based on the typical design pattern because the sender argument can be strongly typed and no longer has to be cast to and from Object.

What is a delegate variable?

A delegate is a reference type variable that holds the reference to a method. The reference can be changed at runtime. Delegates are especially used for implementing events and the call-back methods. All delegates are implicitly derived from the System. Delegate class.


1 Answers

The problem is that an int is not an object.

An int can be boxed to an object. The resulting object (aka boxed int) is, of course, an object, but it's not exactly an int anymore.

Note that the "is" I'm using above is not the same as the C# operator is. My "is" means "is convertible to by implicit reference conversion". This is the meaning of "is" used when we talk about covariance and contravariance.

An int is implicit convertible to an object, but this is not a reference conversion. It has to be boxed.

An House is implicit convertible to an Asset through a reference conversion. There's no need to create or modify any objects.

Consider the example below. Both variables house and asset are referencing the very same object. The variables integer and boxedInt, on the other hand, hold the same value, but they reference different things.

House house = new House();
Asset asset = house;

int integer = 42;
object boxedInt = integer;

Boxing and Unboxing is not as simple as it may look like. It has many subtleties, and might affect your code in unexpected ways. Mixing boxing with covariance and contravariance is an easy way to make anyone dazzle.

like image 145
jpbochi Avatar answered Oct 04 '22 05:10

jpbochi