Использование вариативности в делегатах (C#)

При назначении метода делегату ковариация и контравариантость обеспечивают гибкость сопоставления типа делегата с сигнатурой метода. Ковариация позволяет методу иметь тип возвращаемого значения, степень наследования которого больше, чем указано в делегате. Контравариантность позволяет использовать метод с типами параметров, степень наследования которых меньше, чем у типа делегата.

Пример 1. Ковариация

Description

В этом примере демонстрируется использование делегатов с методами, типы возвращаемых значений которых являются производными от типа возвращаемого значения в сигнатуре делегата. Тип данных, возвращаемый DogsHandler, является типом Dogs, производным от определенного в делегате типа Mammals.

Код

class Mammals {}  
class Dogs : Mammals {}  
  
class Program  
{  
    // Define the delegate.  
    public delegate Mammals HandlerMethod();  
  
    public static Mammals MammalsHandler()  
    {  
        return null;  
    }  
  
    public static Dogs DogsHandler()  
    {  
        return null;  
    }  
  
    static void Test()  
    {  
        HandlerMethod handlerMammals = MammalsHandler;  
  
        // Covariance enables this assignment.  
        HandlerMethod handlerDogs = DogsHandler;  
    }  
}  

Пример 2. Контравариантность

Description

В этом примере демонстрируется использование делегатов с методами, параметры типа которых являются базовыми типами типа параметра сигнатуры делегата. Контравариантность позволяет использовать один обработчик событий вместо нескольких. В следующем примере используется два делегата:

  • Делегат KeyEventHandler, определяющий сигнатуру события Button.KeyDown. Его сигнатура:

    public delegate void KeyEventHandler(object sender, KeyEventArgs e)
    
  • Делегат MouseEventHandler, определяющий сигнатуру события Button.MouseClick. Его сигнатура:

    public delegate void MouseEventHandler(object sender, MouseEventArgs e)
    

В примере определяется обработчик событий с параметром EventArgs, который используется для обработки событий Button.KeyDown и Button.MouseClick. Это может сделать, так как EventArgs это базовый тип обоих KeyEventArgs и MouseEventArgs.

Код

// Event handler that accepts a parameter of the EventArgs type.  
private void MultiHandler(object sender, System.EventArgs e)  
{  
    label1.Text = System.DateTime.Now.ToString();  
}  
  
public Form1()  
{  
    InitializeComponent();  
  
    // You can use a method that has an EventArgs parameter,  
    // although the event expects the KeyEventArgs parameter.  
    this.button1.KeyDown += this.MultiHandler;  
  
    // You can use the same method
    // for an event that expects the MouseEventArgs parameter.  
    this.button1.MouseClick += this.MultiHandler;  
  
}  

См. также