我见过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参数。这两者之间还有其他差异吗?
答案 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函数时,我认为您是在调用堆栈中添加了另一行,但是,嗯。