Jump to content

Делегат (CLI)

Делегат это форма типобезопасного указателя функции, используемая Common Language Infrastructure (CLI). Делегаты указывают метод для вызова и, при необходимости, объект для вызова этого метода. Делегаты используются, помимо прочего, для реализации обратных вызовов и прослушивателей событий . Объект делегата инкапсулирует ссылку на метод. Затем объект делегата можно передать в код, который может вызвать указанный метод, без необходимости знать во время компиляции, какой метод будет вызван.

Делегат многоадресной рассылки — это делегат, указывающий на несколько методов. [1] [2] Многоадресное делегирование — это механизм, обеспечивающий возможность выполнения более чем одного метода. Существует список делегатов, поддерживаемый внутри, и когда вызывается делегат многоадресной рассылки, список делегатов выполняется.

В C# делегаты часто используются для реализации обратных вызовов в программировании, управляемом событиями. Например, делегат может использоваться для указания того, какой метод следует вызывать, когда пользователь нажимает какую-либо кнопку. Делегаты позволяют программисту уведомить несколько методов о произошедшем событии. [3]

Пример кода С#

[ редактировать ]

Код для объявления delegate тип, названный SendMessageDelegate, что занимает Message в качестве параметра и возвращает void:

delegate void SendMessageDelegate(Message message);

Код для определения метода, который принимает экземпляр делегата в качестве аргумента:

void SendMessage(SendMessageDelegate sendMessageDelegateReference)
{
    // Call the delegate and any other chained delegates synchronously.
    sendMessageDelegateReference(new Message("hello this is a sample message"));
}

Реализованный метод, который запускается при вызове делегата:

void HandleSendMessage(Message message)
{
    // The implementation for the Sender and Message classes are not relevant to this example.
    Sender.Send(message);
}

Код для вызова метода SendMessage с передачей экземпляра делегата в качестве аргумента:

SendMessage(new SendMessageDelegate(HandleSendMessage));

Делегаты (C#)

[ редактировать ]
delegate void Notifier(string sender);  // Normal method signature with the keyword delegate

Notifier greetMe;                       // Delegate variable

void HowAreYou(string sender) {
    Console.WriteLine("How are you, " + sender + '?');
}

greetMe = new Notifier(HowAreYou);

Переменная-делегат вызывает связанный метод и вызывается следующим образом:

greetMe("Anton");                       // Calls HowAreYou("Anton") and prints "How are you, Anton?"

Делегатные переменные — это первоклассные объекты вида new DelegateType(obj.Method) и может быть присвоен любому методу сопоставления или значению null. Они хранят метод и его получатель без каких-либо параметров: [4]

new DelegateType(funnyObj.HowAreYou);

Объект funnyObj может быть this и опущено. Если метод static, это должен быть не объект (также называемый экземпляром в других языках), а сам класс. Это не должно быть abstract, но может быть new, override или virtual.

Для успешного вызова метода с делегатом сигнатура метода должна соответствовать DelegateType с одинаковым количеством однотипных параметров ( ref, out, value) того же типа (включая тип возвращаемого значения).

Делегаты многоадресной рассылки (C#)

[ редактировать ]

Переменная-делегат может содержать несколько значений одновременно:

void HowAreYou(string sender)
{
    Console.WriteLine($"How are you, {sender}?");
}

void HowAreYouToday(string sender)
{
    Console.WriteLine($"How are you today, {sender}?");
}

Notifier greetMe;

greetMe = HowAreYou;
greetMe += HowAreYouToday;

greetMe("Leonardo");                  // "How are you, Leonardo?"
                                      // "How are you today, Leonardo?"

greetMe -= HowAreYou;

greetMe("Pereira");                   // "How are you today, Pereira?"

Если делегат многоадресной рассылки является функцией или не имеет out параметр, возвращается параметр последнего вызова. [5]

Детали технической реализации

[ редактировать ]

внутренние реализации могут различаться, экземпляры делегата можно рассматривать как кортеж объекта Хотя , метода указателя и ссылки (возможно, нулевой) на другой делегат. Следовательно, ссылка на одного делегата может быть ссылкой на несколько делегатов. Если после завершения работы первого делегата ссылка на его цепочку не равна нулю, будет вызван следующий и так далее, пока список не будет завершен. Этот шаблон позволяет событие легко масштабировать от одной ссылки до отправки в список делегатов и широко используется в CLI.

Производительность

[ редактировать ]

Раньше производительность делегатов была намного медленнее, чем вызов виртуального или интерфейсного метода (в 6–8 раз медленнее в тестах Microsoft 2003 года). [6] но, начиная с .NET 2.0 CLR в 2005 году, это примерно то же самое, что и вызовы интерфейса. [7] Это означает, что существуют небольшие дополнительные накладные расходы по сравнению с прямым вызовом методов.

Существуют очень строгие правила построения классов делегатов. Эти правила предоставляют оптимизирующим компиляторам большую свободу действий при оптимизации делегатов, обеспечивая при этом безопасность типов. [ нужна ссылка ]

См. также

[ редактировать ]
  1. ^ Статья Microsoft Developer Network (MSDN) , Как объединить делегатов (многоадресные делегаты) (Руководство по программированию на C#) , по состоянию на 20 мая 2008 г.
  2. ^ «О «Делегатах» Microsoft » . Сеть разработчиков Sun. Сан Микросистемс. Архивировано из оригинала 10 февраля 1999 года.
  3. ^ Wikibooks: Программирование C Sharp / Делегаты и события
  4. ^ Мессенбёк, Ханспетер (25 марта 2002 г.). «Расширенный C#: переменное количество параметров» (PDF) . Институт системного программного обеспечения, Университет Иоганна Кеплера в Линце, факультет компьютерных наук. стр. 23–24 . Проверено 4 августа 2011 г.
  5. ^ Мессенбёк, Ханспетер (25 марта 2002 г.). «Расширенный C#: переменное количество параметров» . Институт системного программного обеспечения, Университет Иоганна Кеплера в Линце, факультет компьютерных наук. п. 25 . Проверено 4 августа 2011 г.
  6. ^ Грей, Ян (июнь 2003 г.). «Написание более быстрого управляемого кода: знайте, чего это стоит» . Майкрософт . Проверено 9 сентября 2007 г.
  7. ^ Штурм, Оливер (1 сентября 2005 г.). «В .NET 2 вызовы делегатов значительно ускорились» . Проверено 9 сентября 2007 г.
[ редактировать ]
Arc.Ask3.Ru: конец переведенного документа.
Arc.Ask3.Ru
Номер скриншота №: 09e87881fbf82270723ee25f353fed8c__1671616020
URL1:https://arc.ask3.ru/arc/aa/09/8c/09e87881fbf82270723ee25f353fed8c.html
Заголовок, (Title) документа по адресу, URL1:
Delegate (CLI) - Wikipedia
Данный printscreen веб страницы (снимок веб страницы, скриншот веб страницы), визуально-программная копия документа расположенного по адресу URL1 и сохраненная в файл, имеет: квалифицированную, усовершенствованную (подтверждены: метки времени, валидность сертификата), открепленную ЭЦП (приложена к данному файлу), что может быть использовано для подтверждения содержания и факта существования документа в этот момент времени. Права на данный скриншот принадлежат администрации Ask3.ru, использование в качестве доказательства только с письменного разрешения правообладателя скриншота. Администрация Ask3.ru не несет ответственности за информацию размещенную на данном скриншоте. Права на прочие зарегистрированные элементы любого права, изображенные на снимках принадлежат их владельцам. Качество перевода предоставляется как есть. Любые претензии, иски не могут быть предъявлены. Если вы не согласны с любым пунктом перечисленным выше, вы не можете использовать данный сайт и информация размещенную на нем (сайте/странице), немедленно покиньте данный сайт. В случае нарушения любого пункта перечисленного выше, штраф 55! (Пятьдесят пять факториал, Денежную единицу (имеющую самостоятельную стоимость) можете выбрать самостоятельно, выплаичвается товарами в течение 7 дней с момента нарушения.)