Covariance and Contravariance in Delegates (C# Programming Guide)

Covariance and contravariance provide a degree of flexibility when you match method signatures with delegate types. Covariance permits a method to have a more derived return type than what is defined in the delegate. Contravariance permits a method with parameter types that are less derived than in the delegate type.

Example 1 (Covariance)

Description

This example demonstrates how delegates can be used with methods that have return types that are derived from the return type in the delegate signature. The data type returned by SecondHandler is of type Dogs, which derives from the Mammals type that is defined in the delegate.

Code

class Mammals
{
}

class Dogs : Mammals
{
}

class Program
{
    // Define the delegate. 
    public delegate Mammals HandlerMethod();

    public static Mammals FirstHandler()
    {
        return null;
    }

    public static Dogs SecondHandler()
    {
        return null;
    }

    static void Main()
    {
        HandlerMethod handler1 = FirstHandler;

        // Covariance allows this delegate.
        HandlerMethod handler2 = SecondHandler;
    }
}

Example 2 (Contravariance)

Description

This example demonstrates how delegates can be used with methods that have parameters of a type that are base types of the delegate signature parameter type. With contravariance, you can now use one event handler in places where, previously, you would have had to use separate handlers. For example, you can now create an event handler that accepts an EventArgs input parameter and use it with the Button.MouseClick event that sends a MouseEventArgs type as a parameter, and also with TextBox.KeyDown event that sends a KeyEventArgs parameter.

Code

System.DateTime lastActivity;
public Form1()
{
    InitializeComponent();

    lastActivity = new System.DateTime();
    this.textBox1.KeyDown += this.MultiHandler; //works with KeyEventArgs 
    this.button1.MouseClick += this.MultiHandler; //works with MouseEventArgs

}

// Event hander for any event with an EventArgs or 
// derived class in the second parameter 
private void MultiHandler(object sender, System.EventArgs e)
{
    lastActivity = System.DateTime.Now;
}

See Also

Concepts

C# Programming Guide

Reference

Events (C# Programming Guide)

Delegates (C# Programming Guide)

Generic Delegates (C# Programming Guide)