我正在寻找一些关于在VB.NET中实现自定义事件的指针(Visual Studio 2008,.NET 3.5)。
我知道“常规”(非自定义)事件实际上是Delegates,所以我在实现自定义事件时考虑使用Delegates。另一方面,Andrew Troelsen的"Pro VB 2008 and the .NET 3.5 Platform"书籍在其所有自定义事件示例中使用了集合类型,而Microsoft的sample codes则与该思路相匹配。
所以我的问题是:在选择一种设计而不是另一种设计时,我应该考虑哪些因素?每种设计的优缺点是什么?其中哪些类似于“常规”事件的内部实现?
以下是展示这两种设计的示例代码。
Public Class SomeClass
Private _SomeEventListeners As EventHandler
Public Custom Event SomeEvent As EventHandler
AddHandler(ByVal value As EventHandler)
_SomeEventListeners = [Delegate].Combine(_SomeEventListeners, value)
End AddHandler
RemoveHandler(ByVal value As EventHandler)
_SomeEventListeners = [Delegate].Remove(_SomeEventListeners, value)
End RemoveHandler
RaiseEvent(ByVal sender As Object, ByVal e As System.EventArgs)
_SomeEventListeners.Invoke(sender, e)
End RaiseEvent
End Event
Private _OtherEventListeners As New List(Of EventHandler)
Public Custom Event OtherEvent As EventHandler
AddHandler(ByVal value As EventHandler)
_OtherEventListeners.Add(value)
End AddHandler
RemoveHandler(ByVal value As EventHandler)
_OtherEventListeners.Remove(value)
End RemoveHandler
RaiseEvent(ByVal sender As Object, ByVal e As System.EventArgs)
For Each handler In _OtherEventListeners
handler(sender, e)
Next
End RaiseEvent
End Event
End Class
答案 0 :(得分:3)
我会说使用简单的委托;简单地说 - 它已经已经(内部)一个列表,因此您可以通过将其包装在List<T>
中来重复工作。您还有额外列表对象和数组的开销,可能为null,因此对垃圾收集等影响更大。
此外,如果你正在做 lot ,请考虑EventHandlerList
,它存在以提供对稀疏事件的有效访问 - 即你想暴露的地方许多事件,但其中许多可以取消分配。
第一个示例更接近“标准”事件(尽管您可能希望在调用Invoke
时注意未分配/空处理程序,因为它可能为null)。另外,请注意,有些语言(老实说我不知道VB在这里做了什么)将同步应用于事件,但实际上很少有事件真的需要是线程安全的,所以这可能是过度的。
编辑还会发现它们之间存在功能差异:
List<T>
会)答案 1 :(得分:0)
使用MulticastDelegate来保存订阅事件列表当然是一种可行的方法,但不是我特别热衷的方法。要从MulticastDelegate添加或删除事件,必须执行以下两项操作之一:
如果没有争用,后一种方法可能会提供稍好的性能,但如果许多线程同时尝试添加或删除事件,则可能表现不佳。然而,后一种方法的一个优点是,在握住锁定时没有线程死亡的危险。
这两种方法都不是特别干净。如果计划通过简单地调用委托来调用所有事件,则事件调用性能可能会抵消添加/删除性能。另一方面,如果计划使用GetInvocationList以便在try / catch块中包装事件调用,那么最好只使用(适当锁定的)列表或其他此类数据结构。