Шрифт:
По законам классического наследования в идеале лучше иметь один тип делегата, который мог бы указывать на методы, возвращающие либо тип Car, либо тип SportsCar (в конце концов, тип SportsCar связан с Car отношением наследования). Ковариантность позволяет реализовать именно такую возможность, т.е. построить один делегат, способный указывать на методы, возвращающие типы класса, связанные классическим отношением наследования.
Обратите внимание на то, что тип делегата ObtainVehicalDelegate был определен для того, чтобы указывать на методы, возвращающие строго типизованный Car. Однако в условиях ковариантности мы получаем возможность указывать и на методы, возвращающие производные типы. Чтобы получить производный тип, нужно просто выполнить явное преобразование.
Замечание. Точно так же ковариантность обеспечивает возможность создания делегата, который позволит указать на множество методов, получающих объекты, связанные классическим отношением наследования. Более подробная информация имеется в документации .NET Framework 2.0 SDK.
Исходный код. Проект DelegateCovariance размещен в подкаталоге, соответствующем главе 8.
События в C#
Делегаты оказываются очень интересными конструкциями с той точки зрения, что они предоставляют возможность реализовать двухстороннее взаимодействие между объектами в памяти. Однако, и вы с этим согласитесь, работа с делегата-ми напрямую предполагает ввод больших по объему шаблонных фрагментов программного кода (определение делегата, объявление членов-переменных, создание пользовательских методов регистрации и отмены регистрации).
Поскольку возможность обратного вызови объектов другим объектом является очень полезной, в C# предлагается специальное ключевое слово event, позволяющее минимизировать неудобства программиста, связанные с непосредственным применением делегатов. При обработке ключевого слова event компилятор автоматически создает для вас методы регистрации и отмены регистрации, а также члены-переменные, необходимые для вашего типа делегата. Ключевое слово event Можно назвать синтаксической "конфеткой", позволяющей экономить время при вводе программного кода.
Замечание. Даже при использовании в C# ключевого слова event вам все равно придется вручную определять связанные с делегатом типы.
Процесс определения события состоит из двух шагов. Во-первых, вы должны определить делегат, который будет содержать методы, вызываемые при наступлении соответствующего события. Затем вы объявляете события (используя ключевое слово C# event) в терминах соответствующего делегата. Определение типа, способного посылать события, имеет следующий шаблон (записанный здесь в псевдокоде).
События типа Car будут иметь те же имена, что и предыдущие делегаты (AboutToBlow и Exploded). Новому делегату, с которым будут ассоциироваться события, будет назначено имя CarEventHandler. Вот начальные изменения, вносимые в определение типа Car.