// Новое ускорение (теперь вызывается только myOtherSink)
Console.WriteLine("\n***** Снова ускорение *****);
for(int i = 0; i ‹ 10; i++) cl.Accelerate(20);
// Отключение второго приемника событий.
Console.WriteLine("\n***** Отключение второго приемника *****");
Console.ReadLine;
}
Интерфейсы событий могут быть полезны и тем
Исходный код
. Проект EventInterface размещен в подкаталоге, соответствующем главе 8.Тип делегата .NET
Перед тем как дать формальное определение делегата .NET, давайте обсудим соответствующие перспективы. В Windows API для создания объектов, называемых
Проблема стандартных функций обратного вызова, подобных C, заключается в том, что такие функции, по сути, мало отличаются от простой ссылки на адрес в памяти. В идеале функции обратного вызова могли бы содержать дополнительную обеспечивающую безопасность информацию о числе (и типах) параметров и возвращаемом значении для соответствующего метода. К сожалению, для традиционных функций обратного вызова это не так, и, как вы можете догадаться, (именно это часто оказывается причиной дефектов, которые проявляются в среде выполнения и которые трудно устранить.
Тем не менее, возможность обратного вызова является полезной. В .NET Framework обратный вызов поддерживается» и соответствующие функциональные возможности реализуются с помощью более безопасных методов делегата, что обеспечивает более совершенный объектно-ориентированный подход. В сущности,
•
•
•
Замечание.
В отличие от указателей функций C(++), делегаты .NET могут указывать на статические методы и на методы экземпляра.После создания делегата и получения вышеуказанной информации делегат может динамически в среде выполнения вызывать методы, на которые он указывает. Вы убедитесь, что в .NET Framework каждый делегат .NET (в том числе и ваши пользовательские делегаты) автоматически наделяется способностью вызывать свои методы
Определение делегата в C#
Чтобы создать делегат в C#, вы должны использовать ключевое слово delegate. Имя делегата может быть любым. Однако делегат должен соответствовать методу, на который этот делегат будет указывать. Предположим, например, что нам нужно создать делегат с именем BinaryOp, который сможет указывать на любой метод, возвращающий целое число и имеющий целочисленные входные параметры.
// Этот делегат может указывать на любой метод,
// принимающий два целых значения
// и возвращающий целое значение.
public delegate int BinaryOp(int x, int y);
При обработке типов делегата компилятор C# автоматически генерирует изолированный класс, являющийся производным от System.MulticastDelegate. Этот класс (вместе с базовым классом System.Delegate) обеспечивает делегату необходимую инфраструктуру, позволяющую поддерживать список методов, которые должны быть вызваны позднее. Например, если рассмотреть содержимое делегата BinaryOp с помощью ildasm.exe, вы увидите элементы, показанные на рис. 8.2.
Рис. 8.2. Ключевое слово delegate в C# представляет изолированный тип, производный от System.MulticastDelegate