3

我看到微软建议在 InvokeRequired 模式中使用自定义委托

但是我不明白为什么在做一些像设置控件属性这样简单的事情时,为什么不省去定义委托的麻烦。我指的是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 参数。两者之间还有其他区别吗?

4

2 回答 2

3

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

此外,关于您对 Action 和 Func 的 ByRef 参数的评论,这是正确的,但实现一个接受参数 ByRef 的自定义通用类 Action 类也很简单,如下所示:

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
于 2013-04-03T00:33:00.447 回答
1

Action与 a 相比,Delegate如果你能侥幸成功的话,写起来肯定更简单。

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

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

于 2020-01-15T00:34:04.453 回答