Description of the new covariance and contravariance features and how the lookup behavior for delegates has changed in Visual C# 2005 (913454)



The information in this article applies to:

  • Microsoft Visual C# 2005, Express Edition

SUMMARY

Covariance and contravariance are new features in Microsoft Visual C# 2005. These features provide a degree of flexibility when you match delegate methods with delegate signatures. Because of this flexibility, the lookup behavior for delegates in Visual C# 2005 differs from the behavior in earlier versions of Visual C#.

MORE INFORMATION

In earlier versions of Visual C#, a delegate method must be exactly matched to a delegate signature. To create a successful match, the parameter type and the return type of the delegate method must be identical to the parameter type and the return type of the delegate signature.

In Visual C# 2005, you may notice that more than one match can be established when you work in an inheritance context. In this scenario, delegate behavior may change. The following code samples demonstrate the change in delegate behavior from both the covariance and contravariance perspectives.

Covariance

using System;

delegate object D(); 
 
class A {
  public object M() {return "object";}
}
 
class B:A {
  public string M() {return "string";}
}

public class MyClass {
    public static void Main() {
        B b = new B();
        D d = new D(b.M); 
        Console.WriteLine(d());
    }
}
When you compile and run this code sample in the Microsoft .NET Framework 2.0, you receive a result of "String".

When you compile and run this code sample in the .NET Framework 1.1, you receive a result of "Object". This behavior occurs because only the M method in the base class can be matched exactly with the delegate signature in the .NET Framework 1.1. Therefore, the M method in the base class is assigned to the delegate signature.

In the .NET Framework 2.0, both the M method in the base class and the M method in the derived class can be matched to the delegate signature. However, overload resolution rules decide that the one method in the most specific class wins the match. In this example, the method that is in class B wins the match.

Contravariance

using System;

delegate void D(string s);
 
class A {
  public void M(string s) {Console.WriteLine("string");}
}
 
class B:A {
  public void M(object o) {Console.WriteLine("object");}
}
 
class Program {
  public static void Main() {
    B b = new B();
    D d = new D(b.M);
    d("Message");
  }
}
When you compile and run this code sample in the .NET Framework 2.0, you receive a result of "Object". When you compile and run this code sample in the .NET Framework 1.1, you receive a result of "String". This behavior occurs because of the reasons that are mentioned in the "Covariance" section.

MORE INFORMATION

To change delegate behavior, you can explicitly cast the instance b of the derived class to the base class. For example, you can use the following line of code:
 D d = new D(((A)b).M);

REFERENCES

For more information about covariance and contravariance in delegates, visit the following Microsoft Developer Network (MSDN) Web site:

Modification Type:MajorLast Reviewed:3/3/2006
Keywords:kbExpertiseAdvanced kbinfo KB913454 kbAudDeveloper kbAudITPRO