如何向事件添加动作
How to add an Action to an Event
我有一个通用的事件 class
Public class SomeClass
Public Event ChangeEvent(oldValue As T, newValue As T)
' some code..
End Class
我有一个复杂的方法,我向该方法传递一个 Action(Of T)
,它应该被添加到事件中,然后再被删除。它看起来像下面这样:
Public Sub SomeSub(listener As Action(Of T, T)
AddHandler ChangeEvent, listener
' some code
RemoveHandler ChangeEvent, listener
End Sub
但是编译器在这两行中都给出了以下错误:
Value of type 'Action(Of T, T)' cannot be converted to 'ChangeEventHandler'.
以下有效,但我无法删除处理程序,因为它是一个 lambda 表达式。
Public Sub SomeSub(listener As Action(Of T, T)
AddHandler ChangeEvent, Sub(x, y) listener(x, y)
End Sub
有没有不涉及我将 lambda 存储为成员的解决方案?请注意,我无法更改事件。我只控制添加监听器的方法。
最好显式声明事件处理程序委托,而不是让 Visual Basic 隐式声明它:
Public Class SomeClass(Of T)
Public Delegate Sub ChangeEventHandler(oldValue As T, newValue As T)
Public Event ChangeEvent As ChangeEventHandler
' some code..
End Class
这样您就可以将委托指定为方法的参数,从而为编译器提供正确的签名,并且您可以添加和删除它:
Public Sub SomeSub(listener As ChangeEventHandler)
AddHandler ChangeEvent, listener
' some code...
RemoveHandler ChangeEvent, listener
End Sub
现在你和编译器都开心了! :)
它实际上是这样工作的:
Dim handler As EventHandler
handler = New EventHandler(Sub(s, e)
RemoveHandler anyClass.AnyEvent, handler
' do anything once here ...
End Sub)
AddHandler anyClass.AnyEvent, shownHandler
这将添加处理程序并在事件执行后立即将其删除。所以 lambda 里面的代码只会执行一次。
诀窍是单独声明一个处理程序,因为在 lambda 中,您需要引用变量来删除处理程序。
你根本不需要保留任何成员变量,运行时会为你存储封装好的变量。
但是,您必须确保事件确实被触发(至少一次)。否则,您可能会导致内存泄漏,因为永远不会删除事件处理程序。
我有一个通用的事件 class
Public class SomeClass
Public Event ChangeEvent(oldValue As T, newValue As T)
' some code..
End Class
我有一个复杂的方法,我向该方法传递一个 Action(Of T)
,它应该被添加到事件中,然后再被删除。它看起来像下面这样:
Public Sub SomeSub(listener As Action(Of T, T)
AddHandler ChangeEvent, listener
' some code
RemoveHandler ChangeEvent, listener
End Sub
但是编译器在这两行中都给出了以下错误:
Value of type 'Action(Of T, T)' cannot be converted to 'ChangeEventHandler'.
以下有效,但我无法删除处理程序,因为它是一个 lambda 表达式。
Public Sub SomeSub(listener As Action(Of T, T)
AddHandler ChangeEvent, Sub(x, y) listener(x, y)
End Sub
有没有不涉及我将 lambda 存储为成员的解决方案?请注意,我无法更改事件。我只控制添加监听器的方法。
最好显式声明事件处理程序委托,而不是让 Visual Basic 隐式声明它:
Public Class SomeClass(Of T)
Public Delegate Sub ChangeEventHandler(oldValue As T, newValue As T)
Public Event ChangeEvent As ChangeEventHandler
' some code..
End Class
这样您就可以将委托指定为方法的参数,从而为编译器提供正确的签名,并且您可以添加和删除它:
Public Sub SomeSub(listener As ChangeEventHandler)
AddHandler ChangeEvent, listener
' some code...
RemoveHandler ChangeEvent, listener
End Sub
现在你和编译器都开心了! :)
它实际上是这样工作的:
Dim handler As EventHandler
handler = New EventHandler(Sub(s, e)
RemoveHandler anyClass.AnyEvent, handler
' do anything once here ...
End Sub)
AddHandler anyClass.AnyEvent, shownHandler
这将添加处理程序并在事件执行后立即将其删除。所以 lambda 里面的代码只会执行一次。
诀窍是单独声明一个处理程序,因为在 lambda 中,您需要引用变量来删除处理程序。
你根本不需要保留任何成员变量,运行时会为你存储封装好的变量。
但是,您必须确保事件确实被触发(至少一次)。否则,您可能会导致内存泄漏,因为永远不会删除事件处理程序。