Делегаты и оператор AddressOf
Обновлен: Ноябрь 2007
Делегаты являются объектами, которые можно использовать для вызова методов других объектов. Иногда их описывают как type-safe function pointers, поскольку они аналогичны указателям на функции, используемым в других языках программирования. Но в отличие от указателей на функции, делегаты Visual Basic являются ссылочными типами, основанными на классе, System.Delegate. Делегаты могут ссылаться на оба вида общих методов — методы, которые могут вызываться без определенного экземпляра класса, и методы экземпляров.
Делегаты и события
Применение делегатов особенно эффективно в случаях, когда необходимо посредничество между вызывающей и вызываемой процедурами. Например, необходимо, чтобы объект, инициирующий события, мог вызывать различные обработчики событий при различных условиях. К сожалению, объект, вызвавший события, невозможно знать до того времени, пока обработчик событий не начнет обрабатывать определенное событие. Visual Basic позволяет динамически связывать обработчики событий с событиями путем создания делегата с помощью использования инструкции AddHandler. Во время выполнения делегат передает вызовы соответствующему обработчику событий.
Хотя пользователь может создавать свои собственные делегаты, в большинстве случаев Visual Basic создает делегат в соответствии с имеющимися условиями. Например, оператор Event неявно определяет класс делегата с именем <EventName>EventHandler как вложенный класс класса, содержащего инструкцию Event и с той же подписью, что событие. Оператор AddressOf неявно создает экземпляр делегата. К примеру, следующие две строки кода равносильны:
AddHandler Button1.Click, AddressOf Me.Button1_Click
' The previous line of code is shorthand for the next line of code.
AddHandler Button1.Click, New EventHandler(AddressOf Button1_Click)
В тех случаях, когда компилятор может определить тип делегата по контексту, может быть применен быстрый способ создания делегатов.
Объявление событий, использующих существующий тип делегата
В некоторых случаях бывает необходимо объявить событие для использования существующего типа делегата в качестве основного делегата. Это делается при помощи следующего синтаксиса:
Delegate Sub DelegateType()
Event AnEvent As DelegateType
Такой прием наиболее эффективен, когда нужно направить множество событий к одному и тому же обработчику.
Переменные и параметры делегата
Делегаты можно использовать также для других, не относящихся к событиям задач, таких как свободная работа с потоками. Они могут использоваться и с процедурами, требующими вызова различных версий функций во время компиляции.
Например, имеется приложение рекламного характера, содержащее список с моделями автомобилей. Статьи об автомобилях отсортированы по заголовку, в качестве которого обычно выступает модель автомобиля. Затруднение возникает, если у некоторых автомобилей в имени перед названием модели стоит год их выпуска. Встроенные функции сортируют список по кодам знаков; таким образом, все статьи с годами помещаются в начало списка, а за ними следуют статьи, начинающиеся с модели.
Для исправления данной ошибки в классе можно создать процедуру сортировки, которая использует стандартную сортировку по алфавиту в большинстве списков, но также во время выполнения может переключаться на пользовательскую процедуру сортировки статей об автомобилях. Для этого необходимо передать пользовательскую процедуру сортировки классу сортировки во время выполнения при помощи делегатов.
Каждый класс делегата определяет конструктор, которому передается спецификация метода объекта. Аргумент конструктора делегата должен быть ссылкой на метод или лямбда выражение.
Чтобы указать ссылку на метод, используйте следующий синтаксис:
AddressOf [expression.]methodName
Тип выражения времени компиляции expression должен быть классом или интерфейсом который включает метод с указанным именем, подпись которого соответствует подписи класса делегата. Параметр methodName должен быть совместно используемым методом или методом экземпляра. Параметр methodName не является обязательным, даже если создается делегат для метода класса, используемого по умолчанию.
Чтобы указать выражение лямбда, используйте следующий синтаксис:
Function ([parm As type, parm2 As type2, ...]) expression
Подпись функции должна соответствовать типу делегата. Дополнительные сведения о выражениях лямбда содержатся в разделе Лямбда-выражения.
См. также
Задачи
Практическое руководство. Передача процедур другой процедуре в Visual Basic
Практическое руководство. Вызов метода Delegate
Практическое руководство. Написание обработчиков событий
Основные понятия
Операторы AddHandler и RemoveHandler