Ковариантность и контравариантность делегатов
92C# --- Руководство по C# --- Ковариантность и контравариантность делегатов
Делегаты становятся еще более гибкими средствами программирования благодаря двум свойствам: ковариантности и контравариантности. Как правило, метод, передаваемый делегату, должен иметь такой же возвращаемый тип и сигнатуру, как и делегат. Но в отношении производных типов это правило оказывается не таким строгим благодаря ковариантности и контравариантности. В частности, ковариантность позволяет присвоить делегату метод, возвращаемым типом которого служит класс, производный от класса, указываемого в возвращаемом типе делегата. А контравариантность позволяет присвоить делегату метод, типом параметра которого служит класс, являющийся базовым для класса, указываемого в объявлении делегата.
Ниже приведен пример, демонстрирующий ковариантность и контравариантность:
using System;
namespace ConsoleApplication1
{
delegate Name UI (FamilyAndName obj);
public class Name
{
public string myName;
}
public class FamilyAndName : Name
{
public string Family;
}
public class UserInfo
{
public static Name UIName(Name obj)
{
obj.myName = "Имя пользователя: \"" + obj.myName + "\"";
return obj;
}
public static FamilyAndName UIFamilyName(FamilyAndName obj)
{
obj.Family = "Имя и фамилия: \"" + obj.myName + " " + obj.Family + "\"";
return obj;
}
}
class Program
{
static void Main()
{
// Пример ковариантности
// Можно использовать метод, возвращаемым типом параметра которого
// является производный класс
UI user1 = UserInfo.UIFamilyName;
// Пример контравариантности
// Можно использовать метод, аргументом которого является
// базовый класс
user1 = UserInfo.UIName;
}
}
}
Ковариантность и контравариантность делегатов находит довольно широкое применение при реализации событий.