宽松委托转换(Relaxed delegate conversion)


宽松委托转换(Relaxed delegate conversion)在 Visual Basic 2008 中引入,允许您将子过程或函数赋值给委托或处理器(handlers),尽管它们的签名不一致。因而,绑定到委托变得与绑定方法调用(method invocation)一样。


参数和返回类型


用宽松转换取代精确签名匹配,当 Option Strict 选项要设置为 On 时,需要满足以下两条件:

    * 条件1 传参   
     从委托的每个参数到赋值函数或子过程(assigned function or Sub)的相对应参数,必须存在扩大转换(widening conversion)。在下面的例子中,委托 Del1 有一个 Integer 类型的参数,赋值 lambda 表达式(assigned lambda expressions)的参数 m 的类型必须可以从 Integer 扩大转换,如 Long 或 Double。

       '  定义委托 Del1.
      Delegate  Function  Del1(ByVal arg  As   Integer As   Integer

    
      
'  Option Strict 为 on 或 off, 都是正确的 lambda 表达式赋值

      
'  整型匹配
       Dim  d1  As  Del1  =   Function (m  As   Integer 3

      
'  Integer 扩大为 Long
       Dim  d2  As  Del1  =   Function (m  As   Long 3

      
'  Integer 扩大为 Double
       Dim  d3  As  Del1  =   Function (m  As   Double 3

   
      只有 
Option  Strict 设置为 Off 的时候,才允许缩小转换(Narrowing conversion。    
    

      
'  仅当 Option Strict 为 off 才正确:

      
Dim  d4  As  Del1  =   Function (m  As   String CInt (m)
      
Dim  d5  As  Del1  =   Function (m  As  Short) m

 



    *条件2 返回值
      跟参数相反,从赋值函数或子过程(assigned function or Sub)的返回值类型 到 委托的返回值类型 必须存在扩大转换。下面的例子中,因为委托 Del1的返回类型是 Integer,所以每个赋值 lambda 表达式(assigned lambda expression)必须(可以)扩大到 Integer。

       '  当 Option Strict 为on 时是正确返回值:

      
'  整型匹配.
       Dim  d6  As  Del1  =   Function (m  As   Integer ) m

      
'  Short 扩大为 Integer.
       Dim  d7  As  Del1  =   Function (m  As   Long ) CShort(m)

      
'  Byte 扩大为 Integer.
       Dim  d8  As  Del1  =   Function (m  As   Double CByte (m)

 



如果 Option Strict 设置为 Off,传参和返回值没有扩大转换的限制。

'  仅当 Option Strict 设为 Off 时才正确.

'  Integer 型参数没有扩展为 Short 
Dim  d9  As  Del1  =   Function (n  As  Short) n

'  返回值 Long 型没有扩展为 Integer 
Dim  d10  As  Del1  =   Function (n  As   Integer CLng (n)

 



忽略参数规格

宽松委托(Relaxed delegate)允许您完全忽略赋值方法(assigned method)的参数规格

'  定义委托 Del2, 带两个参数
Delegate  Function  Del2(ByVal arg1  As   Integer , ByVal arg2  As   String As   Integer

'  赋值 lambda 表达式没有参数,尽管 Del2 有两个参数。因为在本例子中赋值函数(assigned function)
'
 是 lambda 表达式,Option Strict 可以是 On 或者 Off。比较 d16 的声明,赋予了标准的方法。
Dim  d11  As  Del2  =   Function ()  3

'  参数仍然要传值,不过类型在委托中定义
Console.WriteLine(d11( 5 " five " ))

'  错误
'
 Console.WriteLine(d11())
'
 Console.WriteLine(d11(5))

 



注意,您不能只列某些参数,而忽略其它参数。

'  错误
'
Dim d12 As Del2 = Function(p As Integer) p

 



忽略参数的特性很有用,特别是在事件处理器(event handler)方面,有很多复杂参数时,而某些参数不使用。这样,处理器直接访问事件所注册控件的状态,并且忽略参数。当不存在歧义时,宽松委托允许您忽略参数。下面的例子,标准的 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 作委托赋值(delegate assignment),类型关系就不那么明显了。

 

下面的例子,函数 f1, f2, f3, 和 f4 可以赋值给 Del1。


'  声明函数委托 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



'  给函数委托 Del1 赋值

'  正确的 AddressOf 赋值,Option Strict 可为 on 或 off:

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

'  整型委托参数扩大为 Long.
Dim  d14  As  Del1  =  AddressOf f2

'  f3 的 Short 返回类型扩大为 Integer.
Dim  d15  As  Del1  =  AddressOf f3


以下例子仅当 
Option  Strict 为 Off 是才正确。

'  如果 Option Strict 设置 Off,f4 的参数规范可以省略
Dim  d16  As  Del1  =  AddressOf f4

'  函数 d16 仍然需要一个参数,在 Del1 定义的
Console.WriteLine(d16( 5 ))

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

 



丢弃函数返回值

宽松委托转换(Relaxed delegate conversion)允许您将一个函数(Function)赋值给子过程委托(Sub delegate),忽略掉函数的返回值。但是您不能够将子过程(Sub)赋值给函数委托(Function Delegate)。下面的例子,函数 doubler 的地址复制给 Sub 委托 Del3。

'  定义 Sub 委托 Del3.
Delegate  Sub  Del3(ByVal arg1  As   Integer )

'  定义函数 doubler, 显示并返回整型参数的值
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


'  您可以把函数赋值给 Sub 委托:
Dim  d17  As  Del3  =  AddressOf doubler

'  您可以向普通 Sub 过程一样调用 d17
d17( 5 )

'  您不可以将 d17 作为函数调用,它是一个 Sub 过程,没有返回值。
'
 错误
'
Console.WriteLine(d17(5))

 


你可能感兴趣的:(conversion)