宽松委托转换 (Visual Basic)
使用宽松委托转换可将子元素和函数分配给委托或处理程序,即使这些委托或处理程序的签名不同。 因此,与委托的绑定将与已允许用于方法调用的绑定相一致。
参数和返回类型
作为取代完全匹配签名的一种方式,宽松转换要求当 Option Strict
设置为 On
时满足以下条件:
必须存在从每个委托参数的数据类型,到已分配函数或
Sub
的相应参数的数据类型的扩大转换。 在以下示例中,委托Del1
有一个参数,即Integer
。 分配的 lambda 表达式中的参数m
必须具有一个数据类型(例如Long
或Double
),该类型存在从Integer
进行的扩大转换。' 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
的返回类型到委托的返回类型)必须存在一个扩大转换。 在以下示例中,每个已分配的 lambda 表达式的主体必须计算为扩大为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 示例
为了轻松发现类型关系,以上示例中使用了 Lambda 表达式。 但是,对于使用 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
的地址将分配给 Sub
委托 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))