Ковариантность и контравариантность делегатов
Делегаты становятся еще более гибкими средствами программирования благодаря двум свойствам: ковариантности и контравариантности. Как правило, метод, передаваемый делегату, должен иметь такой же возвращаемый тип и сигнатуру, как и делегат. Но в отношении производных типов это правило оказывается не таким строгим благодаря ковариантности и контравариантности. В частности, ковариантность позволяет присвоить делегату метод, возвращаемым типом которого служит класс, производный от класса, указываемого в возвращаемом типе делегата. А контравариантность позволяет присвоить делегату метод, типом параметра которого служит класс, являющийся базовым для класса, указываемого в объявлении делегата.
Ниже приведен пример, демонстрирующий ковариантность и контравариантность:
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; } } }
Ковариантность и контравариантность делегатов находит довольно широкое применение при реализации событий.
Комментарии