Делегат является формой типобезопасного указателя функции , используемой инфраструктуры общего языка (CLI). Делегаты указывают метод для вызова и, необязательно, объект для вызова метода. Делегаты используются, среди прочего, для реализации обратных вызовов и прослушивателей событий . Объект делегата инкапсулирует ссылку на метод. Объект делегата может быть передан кодом , который можно называть ссылаются метод, без необходимости знать во время компиляции , который будет вызван метод.
Групповой делегат является делегат , который указывает на несколько методов. [1] [2] Многоадресное делегирование - это механизм, который обеспечивает функциональность для выполнения более чем одного метода. Существует список делегатов, поддерживаемый внутри, и когда вызывается делегат многоадресной рассылки, список делегатов выполняется.
В C # делегаты часто используются для реализации обратных вызовов в программировании, управляемом событиями. Например, делегат может использоваться, чтобы указать, какой метод должен вызываться, когда пользователь нажимает какую-либо кнопку. Делегаты позволяют программисту уведомлять несколько методов о том, что произошло событие. [3]
Пример кода C #
Код для объявления delegateтипа с именем SendMessageDelegate, который принимает Messageв качестве параметра и возвращает void:
делегат void SendMessageDelegate ( сообщение- сообщение );
Код для определения метода, который принимает созданный экземпляр делегата в качестве аргумента:
void SendMessage ( SendMessageDelegate sendMessageDelegateReference ) { // Вызов делегата и любых других связанных делегатов синхронно. sendMessageDelegateReference ( новое сообщение ( "привет, это образец сообщения" )); }
Реализованный метод, который запускается при вызове делегата:
void HandleSendMessage ( Message message ) { // Реализация для классов Sender и Message не имеет отношения к этому примеру. Отправитель . Отправить ( сообщение ); }
Код для вызова метода SendMessage с передачей созданного делегата в качестве аргумента:
SendMessage ( новый SendMessageDelegate ( HandleSendMessage ));
Делегаты (C #)
делегировать void Notifier ( отправитель строки ); // Обычная сигнатура метода с ключевым словом delegate Notifier greetMe ; // Делегирующая переменнаяvoid HowAreYou ( отправитель строки ) { Console . WriteLine ( "Как дела" + отправитель + '?' ); } greetMe = новый Notifier ( HowAreYou );
Переменная делегата вызывает связанный метод и вызывается следующим образом:
greetMe ( "Антон" ); // Вызывает HowAreYou ("Антон") и выводит "Как дела, Антон?"
Переменные-делегаты являются первоклассными объектами формы и могут быть присвоены любому методу сопоставления или значению . Они хранят метод и его получатель без каких-либо параметров: [4]new DelegateType(obj.Method)
null
новый DelegateType ( funnyObj . HowAreYou );
Объект funnyObj
можно this
и опустить. Если метод есть static
, это должен быть не объект (также называемый экземпляром на других языках), а сам класс. Это не должно быть abstract
, но может быть new
, override
или virtual
.
Для успешного вызова метода с делегатом, метод подписи должен соответствовать DelegateType
с тем же числом параметров одного и того же вида ( ref
, out
, value
) с тем же типом (включая тип возвращаемого значения).
Делегаты многоадресной рассылки (C #)
Переменная делегата может одновременно содержать несколько значений:
void HowAreYou ( отправитель строки ) { Console . WriteLine ( "Как дела" + отправитель + '?' ); } void HowAreYouToday ( отправитель строки ) { Console . WriteLine ( «Как дела?» + Отправитель + '?' ); } Notifier greetMe ;greetMe = HowAreYou ; greetMe + = HowAreYouToday ;greetMe ( "Леонардо" ); // "Как дела, Леонардо?" // "Как дела, Леонардо?"greetMe - = HowAreYou ;greetMe ( "Перейра" ); // "Как дела, Перейра?"
Если делегат многоадресной рассылки является функцией или не имеет out
параметра, возвращается параметр последнего вызова. [5]
Детали технической реализации
Хотя внутренние реализации могут различаться, делегировать экземпляры можно рассматривать как кортеж из качестве объекта и методы указатель и ссылки (возможно , нулевой) на другой делегат. Следовательно, ссылка на одного делегата может быть ссылкой на несколько делегатов. Когда первый делегат завершит работу, если его ссылка на цепочку не равна нулю, будет вызван следующий и так далее, пока список не будет завершен. Этот шаблон позволяет событию легко масштабировать накладные расходы от одиночной ссылки до отправки списку делегатов и широко используется в CLI.
Представление
Раньше производительность делегатов была намного ниже, чем при вызове виртуального или интерфейсного метода (в 6-8 раз медленнее в тестах Microsoft 2003), [6] но, начиная с .NET 2.0 CLR в 2005 году, она примерно такая же, как вызовы интерфейса. [7] Это означает, что есть небольшие дополнительные накладные расходы по сравнению с прямым вызовом методов.
Существуют очень строгие правила построения классов делегатов. Эти правила дают оптимизирующим компиляторам большую свободу действий при оптимизации делегатов, обеспечивая при этом безопасность типов. [ необходима цитата ]
Смотрите также
Рекомендации
- ^ Статья Microsoft Developer Network (MSDN) , Как объединить делегатов (многоадресные делегаты) (Руководство по программированию на C #) , дата обращения 20.05.2008.
- ^ «О компании Microsoft„Делегаты “ » . Sun Developer Network . Sun Microsystems. Архивировано из оригинального 10 февраля 1999 года.
- ^ Викиучебники: Программирование C Sharp / Делегаты и события
- ^ Мёссенбёк, Ханспетер (25 марта 2002 г.). «Расширенный C #: переменное количество параметров» (PDF) . http://ssw.jku.at/Teaching/Lectures/CSharp/Tutorial/ : Institut für Systemsoftware, Университет Йоханнеса Кеплера в Линце, Fachbereich Informatik. С. 23–24 . Проверено 4 августа 2011 .
- ^ Мёссенбёк, Ханспетер (25 марта 2002 г.). «Расширенный C #: переменное количество параметров» . Institut für Systemsoftware, Университет Йоханнеса Кеплера в Линце, Fachbereich Informatik. п. 25 . Проверено 4 августа 2011 .
- ^ Грей, янв (июнь 2003 г.). «Написание более быстрого управляемого кода: знайте, чего стоит» . Microsoft . Проверено 9 сентября 2007 .
- ^ Штурм, Оливер (01.09.2005). «В .NET 2 значительно ускорились вызовы делегатов» . Проверено 9 сентября 2007 .