宽松委托转换 (Visual Basic)Relaxed Delegate Conversion (Visual Basic)

通过宽松委托转换,您可以将 sub 和函数分配给委托或处理程序,即使它们的签名不相同。Relaxed delegate conversion enables you to assign subs and functions to delegates or handlers even when their signatures are not identical. 因此,绑定到委托将与已允许方法调用的绑定一致。Therefore, binding to delegates becomes consistent with the binding already allowed for method invocations.

参数和返回类型Parameters and Return Type

宽松转换要求在将 Option Strict 设置为 On时满足以下条件:In place of exact signature match, relaxed conversion requires that the following conditions be met when Option Strict is set to On:

  • 必须将每个委托参数的数据类型的扩大转换为分配的函数或 Sub的相应参数的数据类型。A widening conversion must exist from the data type of each delegate parameter to the data type of the corresponding parameter of the assigned function or Sub. 在下面的示例中,委托 Del1 具有一个参数,即一个 IntegerIn the following example, the delegate Del1 has one parameter, an Integer. 已分配 lambda 表达式中的参数 m 必须具有一个数据类型,该数据类型的数据类型为,其中存在从 Integer的扩大转换,如 LongDoubleParameter m in the assigned lambda expressions must have a data type for which there is a widening conversion from Integer, such as Long or 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时,才允许收缩转换。Narrowing conversions are permitted only when Option Strict is set to 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 为委托的返回类型的方向相反。A widening conversion must exist in the opposite direction from the return type of the assigned function or Sub to the return type of the delegate. 在下面的示例中,每个已分配 lambda 表达式的主体的计算结果都必须是扩大到 Integer 的数据类型,因为 del1 的返回类型是 Integer的。In the following examples, the body of each assigned lambda expression must evaluate to a data type that widens to Integer because the return type of del1 is 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,则将在这两个方向上删除扩大限制。If Option Strict is set to Off, the widening restriction is removed in both directions.

' 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)

省略参数规范Omitting Parameter Specifications

宽松委托还允许您完全省略分配的方法中的参数规范:Relaxed delegates also allow you to completely omit parameter specifications in the assigned method:

' 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))

请注意,不能指定某些参数并忽略其他参数。Note that you cannot specify some parameters and omit others.

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

在某些情况下,忽略参数的功能非常有用,例如定义一个事件处理程序,其中涉及多个复杂参数。The ability to omit parameters is helpful in a situation such as defining an event handler, where several complex parameters are involved. 不使用某些事件处理程序的参数。The arguments to some event handlers are not used. 相反,处理程序将直接访问在其上注册事件的控件的状态,并忽略参数。Instead, the handler directly accesses the state of the control on which the event is registered, and ignores the arguments. 宽松的委托允许在没有歧义结果时省略此类声明中的参数。Relaxed delegates allow you to omit the arguments in such declarations when no ambiguities result. 在下面的示例中,OnClick 的完全指定方法可以重写为 RelaxedOnClickIn the following example, the fully specified method OnClick can be rewritten as 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 Examples

前面的示例中使用了 Lambda 表达式,使类型关系易于查看。Lambda expressions are used in the previous examples to make the type relationships easy to see. 但是,允许使用 AddressOfHandlesAddHandler的委托分配使用相同的松弛法。However, the same relaxations are permitted for delegate assignments that use AddressOf, Handles, or AddHandler.

在下面的示例中,函数 f1f2f3f4 都可以分配给 Del1In the following example, functions f1, f2, f3, and f4 can all be assigned to 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时,下面的示例才有效。The following example is valid only when Option Strict is set to 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))

删除函数返回Dropping Function Returns

通过宽松委托转换,您可以将函数分配给 Sub 委托,从而有效地忽略函数的返回值。Relaxed delegate conversion enables you to assign a function to a Sub delegate, effectively ignoring the return value of the function. 但是,不能向函数委托分配 SubHowever, you cannot assign a Sub to a function delegate. 在下面的示例中,函数 doubler 的地址分配给 Sub 委托 Del3In the following example, the address of function doubler is assigned to Sub delegate Del3.

' 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))

另请参阅See also