使用自定义委托与操作调用方法

时间:2013-04-02 22:40:43

标签: .net vb.net invoke

我见过Microsoft建议使用a custom Delegate in the InvokeRequired pattern

但我无法弄清楚为什么在做一些像设置控件属性这样简单的事情时,不会省去定义委托的麻烦。我指的是下面的Option 1,它只使用委托Action(Of String)而不是自定义委托。

' Option 1

Private Sub setLabelWorkingText(ByVal [text] As String)
    If Me.lblWorking.InvokeRequired Then
        Me.Invoke(New Action(Of String)(AddressOf setLabelWorkingText), [text])
    Else
        Me.lblWorking.Text = [text]
    End If
End Sub

' Option 2

Private Delegate Sub setLabelWorkingTextDelegate(ByVal [text] As String)

Private Sub setLabelWorkingTextWithDel(ByVal [text] As String)
    If Me.lblWorking.InvokeRequired Then
        Me.Invoke(New setLabelWorkingTextDelegate(AddressOf setLabelWorkingTextWithDel), [text])
    Else
        Me.lblWorking.Text = [text]
    End If
End Sub

我理解一个区别是参数不能使用Action和Func传递给ByRef,但是自定义委托可以指定ByRef参数。这两者之间还有其他差异吗?

2 个答案:

答案 0 :(得分:2)

Action本质上是一个通过泛型定义的自定义委托。我猜测你链接的模式中没有指定的原因是模式和Action委托同时开发/发布,开发模式和文档的人可能不熟悉Action泛型在发布时。您会注意到,在框架的后续版本中,Action更常用于示例和模式中,因为它已被接受。

另外,关于你对Action和Func的ByRef参数的评论,这是正确的,但是实现一个类似Action的自定义类接受参数ByRef也是微不足道的,如:

Public Delegate Sub ActionByRef(Of T)(ByRef ref As T)

Sub Main()
    Dim sMyString As String = "Hello World"
    Dim actTrim As New ActionByRef(Of String)(AddressOf TrimFirst)
    actTrim.Invoke(sMyString)
    Console.WriteLine(sMyString) 'prints "ello World"
    Console.ReadLine()
End Sub

Sub TrimFirst(ByRef s As String)
    s = s.Substring(1)
End Sub

答案 1 :(得分:0)

如果可以避免的话,写Action比写Delegate绝对简单。

Action仅允许您“将方法作为参数传递而无需显式声明自定义委托”。 Source

当您传递lambda函数时,我认为您是在调用堆栈中添加了另一行,但是,嗯。