New Features in C# 2.0—Co- and Contravariance: What just happened?
Microsoft .NET Framework, ASP.NET, Visual C# (CSharp, C Sharp, C-Sharp) Developer Training, Visual Studio
What just happened?
The Program class in Example 1-10 declares two delegates. The first is
for a method that takes no parameters and returns a Mammal:
public delegate Mammal theCovariantMethod( );
In the run method, you declare an instance of Mammal and an instance of
Dog:
Mammal m = new Mammal(); Dog d = new Dog();
Earlier in the file you declared Dog to derive from Mammal.
|
You are ready to create your first instance of theCovariantDelegate:
theCovariantDelegate myCovariantDelegate = new theCovariantDelegate(m.ReturnsMammal);
This matches the delegate signature (m.ReturnsMammal( ) is a method
that takes no parameters and returns a Mammal), so you can invoke the
method through the delegate:
myCovariantDelegate( );
Now you use covariance to encapsulate a second method within the same delegate:
myCovariantDelegate = new theCovariantDelegate(d.ReturnsDog);
This time, however, you are passing in a method (d.ReturnsDog( )) that
does not return a Mammal; it returns a Dog that derives from Mammal:
public Dog ReturnsDog( ) { Console.WriteLine("Returning a dog"); return this; }
That is covariance at work. To see contravariance, you declare a second
delegate to encapsulate a method that returns null and takes a Dog as a
parameter:
public delegate void theContravariantDelegate(Dog theDog);
Your first instantiation of this delegate encapsulates a method with the
appropriate return value (void) and parameter (Dog):
myContravariantDelegate = new theContravariantDelegate(MyMethodThatTakesADog);
| Notice that with contravariance, you can pass in an object of the base type as a parameter where an object of the derived type is expected. |
You can invoke the method through the delegate. Your second use of this
delegate, however, encapsulates a method that does not take a Dog as a
parameter, but rather, takes a Mammal as a parameter:
theContravariantDelegate myContravariantDelegate = new theContravariantDelegate(MyMethodThatTakesAMammal);
MyMethodThatTakesAMammal is defined to take a Mammal, not a Dog, as a
parameter:
private void MyMethodThatTakesAMammal(Mammal theMammal) { Console.WriteLine("in My Method That Takes A Mammal"); }
Again, this works because a Dog is a Mammal and contravariance allows
you to make this substitution.
|

