Неявное преобразование делегата (Visual Basic)

Гибкое преобразование в тип делегата позволяет присваивать делегатам или обработчикам подпрограммы и функции, даже когда их сигнатуры не идентичны. Таким образом, привязка к делегатам становится согласованной с привязкой, уже разрешенной для вызовов метода. 

Параметры и тип возвращаемого значения

Вместо сопоставления точной сигнатуры ослабленное преобразование требует следующих условий при установке Option Strict в On:

  • Должно существовать расширяющее преобразование типа данных каждого параметра делегата к типу данных соответствующего параметра назначенной функции или Sub.В следующем примере делегат Del1 имеет один параметр типа Integer.Параметр m в назначенном лямбда-выражении должен иметь тип данных для которых имеется расширяющее преобразование из Integer, например Long или Double.

    ' Definition of delegate Del1.
    Delegate Function Del1(ByVal arg As Integer) As Integer
    
    ' Valid lambda expression assignments with Option Strict on or off:
    
    ' Integer matches Integer.
    Dim d1 As Del1 = Function(m As Integer) 3
    
    ' Integer widens to Long
    Dim d2 As Del1 = Function(m As Long) 3
    
    ' Integer widens to Double
    Dim d3 As Del1 = Function(m As Double) 3
    

    Сужающие преобразования разрешены только в том случае, если Option Strict имеет значение Off.

    ' Valid only when Option Strict is off:
    
    Dim d4 As Del1 = Function(m As String) CInt(m)
    Dim d5 As Del1 = Function(m As Short) m
    
  • Должно существовать расширяющее преобразование в обратном направлении из возвращаемого типа назначенной функции или Sub к возвращаемому типу делегата.В следующих примерах, основная часть каждого назначенного лямбда-выражения должно иметь значение типа данных, не большего по разрядности, чем Integer, так как возвращаемым типом del1 является тип Integer.

    ' Valid return types with Option Strict on:
    
    ' Integer matches Integer.
    Dim d6 As Del1 = Function(m As Integer) m
    
    ' Short widens to Integer.
    Dim d7 As Del1 = Function(m As Long) CShort(m)
    
    ' Byte widens to Integer.
    Dim d8 As Del1 = Function(m As Double) CByte(m)
    

Если Option Strict имеет значение Off, расширяющее ограничение снимается в обоих направлениях.

' Valid only when Option Strict is set to Off.

' Integer does not widen to Short in the parameter.
Dim d9 As Del1 = Function(n As Short) n

' Long does not widen to Integer in the return type.
Dim d10 As Del1 = Function(n As Integer) CLng(n)

Пропуск параметра спецификации

Ослабленные делегаты также позволяют полностью опустить параметры спецификации в назначенном методе:

' Definition of delegate Del2, which has two parameters.
Delegate Function Del2(ByVal arg1 As Integer, ByVal arg2 As String) As Integer
' The assigned lambda expression specifies no parameters, even though
' Del2 has two parameters. Because the assigned function in this 
' example is a lambda expression, Option Strict can be on or off.
' Compare the declaration of d16, where a standard function is assigned.
Dim d11 As Del2 = Function() 3

' The parameters are still there, however, as defined in the delegate.
Console.WriteLine(d11(5, "five"))

' Not valid.
' Console.WriteLine(d11())
' Console.WriteLine(d11(5))

Обратите внимание, что не удается задать некоторые параметры и не указать другие.

' Not valid.
'Dim d12 As Del2 = Function(p As Integer) p

Возможность опустить параметры является полезной в ситуации, например при определении обработчика событий, где включены несколько сложных параметров.Аргументы для некоторых обработчиков событий не используются.Вместо этого обработчик непосредственно получает состояние элемента управления, к которому привязано событие, а аргументы игнорируются.Ослабленные делегаты позволяют опустить аргументы в таких объявлениях, когда результат неоднозначен.В следующем примере полностью заданный метод OnClick можно переписать как RelaxedOnClick.

Sub OnClick(ByVal sender As Object, ByVal e As EventArgs) Handles b.Click
    MessageBox.Show("Hello World from" + b.Text)
End Sub

Sub RelaxedOnClick() Handles b.Click
    MessageBox.Show("Hello World from" + b.Text)
End Sub

Примеры AddressOf

Лямбда-выражения используются в предыдущих примерах, чтобы облегчить наблюдение за связью между типами.Однако ослабление разрешено для назначений делегата, которые используют AddressOf, Handles или AddHandler.

В следующем примере функции f1, f2, f3 и f4 могут быть назначены Del1.

' Definition of delegate Del1.
Delegate Function Del1(ByVal arg As Integer) As Integer
' Definitions of f1, f2, f3, and f4.
Function f1(ByVal m As Integer) As Integer
End Function

Function f2(ByVal m As Long) As Integer
End Function

Function f3(ByVal m As Integer) As Short
End Function

Function f4() As Integer
End Function
' Assignments to function delegate Del1.

' Valid AddressOf assignments with Option Strict on or off:

' Integer parameters of delegate and function match.
Dim d13 As Del1 = AddressOf f1

' Integer delegate parameter widens to Long.
Dim d14 As Del1 = AddressOf f2

' Short return in f3 widens to Integer.
Dim d15 As Del1 = AddressOf f3

Следующей пример справедлив только в том случае, если Option Strict имеет значение Off.

' If Option Strict is Off, parameter specifications for f4 can be omitted.
Dim d16 As Del1 = AddressOf f4

' Function d16 still requires a single argument, however, as specified
' by Del1.
Console.WriteLine(d16(5))

' Not valid.
'Console.WriteLine(d16())
'Console.WriteLine(d16(5, 3))

Игнорирование возвращаемого значения функции

Ослабленный делегат преобразования позволяет назначить функцию делегату Sub, при этом игнорируя значение, возвращаемое функцией.Однако присвоить Sub делегату функции невозможно.В следующем примере адрес функции doubler присваивается делегату SubDel3.

' Definition of Sub delegate Del3.
Delegate Sub Del3(ByVal arg1 As Integer)

' Definition of function doubler, which both displays and returns the
' value of its integer parameter.
Function doubler(ByVal p As Integer) As Integer
    Dim times2 = 2 * p
    Console.WriteLine("Value of p: " & p)
    Console.WriteLine("Double p:   " & times2)
    Return times2
End Function
' You can assign the function to the Sub delegate:
Dim d17 As Del3 = AddressOf doubler

' You can then call d17 like a regular Sub procedure.
d17(5)

' You cannot call d17 as a function. It is a Sub, and has no 
' return value.
' Not valid.
'Console.WriteLine(d17(5))

См. также

Задачи

Практическое руководство. Передача процедур другой процедуре в Visual Basic

Ссылки

Оператор Option Strict

Основные понятия

Лямбда-выражения (Visual Basic)

Расширяющие и сужающие преобразования (Visual Basic)

Вывод локального типа (Visual Basic)

Другие ресурсы

Делегаты (Visual Basic)