Делегаты (Visual Basic)
Делегаты — это объекты, которые ссылаются на методы.Иногда их описывают как type-safe function pointers, поскольку они аналогичны указателям на функции, используемым в других языках программирования.Но в отличие от указателей на функции, делегаты Visual Basic являются ссылочными типами, основанными на классе, System.Delegate.Делегаты могут ссылаться на оба вида общих методов — методы, которые могут вызываться без определенного экземпляра класса, и методы экземпляров.
Делегаты и события
Применение делегатов особенно эффективно в случаях, когда необходимо посредничество между вызывающей и вызываемой процедурами.Например, необходимо, чтобы объект, инициирующий события, мог вызывать различные обработчики событий при различных условиях.К несчастью, объект, вызывающий события, не может заранее знать время, когда обработчик событий обрабатывает конкретное событие.Visual Basic позволяет динамически связывать обработчики событий с событиями путем создания делегата при использовании оператора AddHandler.Во время выполнения делегат передает вызовы соответствующему обработчику событий.
Хотя пользователь может создавать свои собственные делегаты, в большинстве случаев Visual Basic создает делегат в соответствии с имеющимися условиями.Например, оператор Event неявно определяет класс делегата с именем <EventName>EventHandler как вложенный класс класса, содержащего инструкцию Event и с той же сигнатурой, что событие.Оператор AddressOf неявно создает экземпляр делегата, который ссылается на конкретную процедуру.Приведенные далее две строки кода равнозначны.В первой строке можно видеть явное создание экземпляра Eventhandler со ссылкой на метод Button1_Click, отправленной в качестве аргумента.Вторая строка представляет более удобный способ получения того же результата.
AddHandler Button1.Click, New EventHandler(AddressOf Button1_Click)
' The following line of code is shorthand for the previous line.
AddHandler Button1.Click, AddressOf Me.Button1_Click
В тех случаях, когда компилятор может определить тип делегата по контексту, может быть применен быстрый способ создания делегатов.
Объявление событий, использующих существующий тип делегата
В некоторых случаях бывает необходимо объявить событие для использования существующего типа делегата в качестве основного делегата.Это делается при помощи следующего синтаксиса:
Delegate Sub DelegateType()
Event AnEvent As DelegateType
Такой прием наиболее эффективен, когда нужно направить множество событий к одному и тому же обработчику.
Переменные и параметры делегата
Делегаты можно использовать также для других, не связанных с событиями задач, таких как свободная работа с потоками. Они могут использоваться и с процедурами, требующими вызова различных версий функций во время выполнения.
Например, имеется приложение рекламного характера, содержащее список с моделями автомобилей.Статьи об автомобилях отсортированы по заголовку, в качестве которого обычно выступает модель автомобиля.Затруднение возникает, если у некоторых автомобилей в имени перед названием модели стоит год их выпуска.Встроенные функции сортируют список по кодам знаков; таким образом, все статьи с годами помещаются в начало списка, а за ними следуют статьи, начинающиеся с модели.
Для исправления данной ошибки в классе можно создать процедуру сортировки, которая использует стандартную сортировку по алфавиту в большинстве списков, но также во время выполнения может переключаться на пользовательскую процедуру сортировки статей об автомобилях.Для этого необходимо передать пользовательскую процедуру сортировки классу сортировки во время выполнения при помощи делегатов.
AddressOf и лямбда-выражения
Каждый класс делегата определяет конструктор, которому передается спецификация метода объекта.Аргумент конструктора делегата должен быть ссылкой на метод или лямбда выражение.
Чтобы указать ссылку на метод, используйте следующий синтаксис:
AddressOf [expression.]methodName
Тип выражения времени компиляции expression должен быть классом или интерфейсом который включает метод с указанным именем, сигнатура которого соответствует сигнатуре класса делегата.Параметр methodName должен быть совместно используемым методом или методом экземпляра.Параметр methodName не является обязательным, даже если создается делегат для метода класса, используемого по умолчанию.
Чтобы указать выражение лямбда, используйте следующий синтаксис:
Function ([parm As type, parm2 As type2, ...]) expression
В следующем примере показано задание ссылки для делегата с помощью AddressOf и лямбда-выражений.
Module Module1
Sub Main()
' Create an instance of InOrderClass and assign values to the properties.
' InOrderClass method ShowInOrder displays the numbers in ascending
' or descending order, depending on the comparison method you specify.
Dim inOrder As New InOrderClass
inOrder.Num1 = 5
inOrder.Num2 = 4
' Use AddressOf to send a reference to the comparison function you want
' to use.
inOrder.ShowInOrder(AddressOf GreaterThan)
inOrder.ShowInOrder(AddressOf LessThan)
' Use lambda expressions to do the same thing.
inOrder.ShowInOrder(Function(m, n) m > n)
inOrder.ShowInOrder(Function(m, n) m < n)
End Sub
Function GreaterThan(ByVal num1 As Integer, ByVal num2 As Integer) As Boolean
Return num1 > num2
End Function
Function LessThan(ByVal num1 As Integer, ByVal num2 As Integer) As Boolean
Return num1 < num2
End Function
Class InOrderClass
' Define the delegate function for the comparisons.
Delegate Function CompareNumbers(ByVal num1 As Integer, ByVal num2 As Integer) As Boolean
' Display properties in ascending or descending order.
Sub ShowInOrder(ByVal compare As CompareNumbers)
If compare(_num1, _num2) Then
Console.WriteLine(_num1 & " " & _num2)
Else
Console.WriteLine(_num2 & " " & _num1)
End If
End Sub
Private _num1 As Integer
Property Num1() As Integer
Get
Return _num1
End Get
Set(ByVal value As Integer)
_num1 = value
End Set
End Property
Private _num2 As Integer
Property Num2() As Integer
Get
Return _num2
End Get
Set(ByVal value As Integer)
_num2 = value
End Set
End Property
End Class
End Module
Сигнатура функции должна соответствовать типу делегата.Дополнительные сведения о лямбда-выражениях см. в разделе Лямбда-выражения (Visual Basic).Дополнительные примеры назначения делегатам лямбда-выражений и AddressOf см. в разделе Неявное преобразование делегата (Visual Basic).
Связанные разделы
Заголовок |
Описание |
---|---|
Практическое руководство. Вызов метода делегата (Visual Basic) |
Содержит пример, в котором показано, как связать метод с делегатом, а затем вызвать метод через делегат. |
Практическое руководство. Передача процедур другой процедуре в Visual Basic |
Демонстрирует использование делегатов для передачи одной процедуры в другую. |
Описание способов присвоения делегатам или обработчикам подпрограмм и функций, даже когда их подписи не идентичны. |
|
Содержит общие сведения о событиях в Visual Basic. |