SQLConnection.StateChange使用StateChangeEventHandler和AddressOf的事件AddHandler

时间:2014-05-09 16:33:07

标签: c# .net vb.net events event-handling

SQLConnection.StateChange事件添加事件处理程序的这两种不同方式有何不同,副作用和/或偏好?由于AddressOf创建了委托(http://msdn.microsoft.com/en-us/library/y72ewk2b.aspx),而StateChangeEventHandler也是委托,因此示例2似乎只是创建嵌套委托,但我猜测有一些委托我失踪的细微差别。

从我的测试中,它们似乎使用示例1或2工作相同。在尝试多次调用AddHandler时都没有抛出异常(我的第一个假设是,如果尝试调用AddHandler,调用示例#1会引发错误第二次,因为它将添加相同的引用,因为示例2不会,因为它将是一个新的委托实例;但是,它们都成功,没有例外)。

示例1:仅使用AddressOfhttp://msdn.microsoft.com/en-us/library/7taxzxka.aspx

AddHandler conn.StateChange, AddressOf OnConnectionStateChange

示例2 :使用此处列出的StateChangeEventHandler代理人的实例:http://msdn.microsoft.com/en-us/library/a0hee08w(v=vs.110).aspx?cs-save-lang=1&cs-lang=vb#code-snippet-2

AddHandler conn.StateChange, New StateChangeEventHandler(AddressOf OnConnectionStateChange)

此外,是否需要在using阻止RemoveHandler阻止通过SQLConnection.Dispose之前删除此处理程序,或者StateChangeEventHandler会为您处理这个问题?我不确定如果在MSDN网站中使用下面示例#2中的StateChangeEventHandler,将如何删除事件处理程序,因为RemoveHandler委托的实例未存储在本地变量中,因此,您没有要删除的处理程序的引用(您必须执行与示例#4类似的操作)。

示例#3: AddressOf仅使用 Using conn As SqlConnection = New SqlConnection("...") AddHandler conn.StateChange, AddressOf OnConnectionStateChange conn.Open() '...do work here... conn.Close() 'Then do i need this? RemoveHandler conn.StateChange, AddressOf OnConnectionStateChange End Using

RemoveHandler

示例#4: StateChangeEventHandler使用 Using conn As SqlConnection = New SqlConnection("...") Dim myHandler As StateChangeEventHandler = New StateChangeEventHandler(AddressOf OnConnectionStateChange) AddHandler conn.StateChange, myHandler conn.Open() '...do work here... conn.Close() 'Then do i need this? RemoveHandler conn.StateChange, myHandler End Using

connection.StateChange  += new StateChangeEventHandler(OnStateChange);

注意:我也标记为C#,因为MSDN文档也列出了C#示例的相同场景:

connection.StateChange  += OnStateChange;

VS。

{{1}}

1 个答案:

答案 0 :(得分:0)

我偶然发现了这篇文章(http://msdn.microsoft.com/en-us/library/74wy9422(v=vs.90).aspx),其中提到AddressOf只是New EventHandler(AddressOf fn)的简写。

AddHandler Button1.Click, New EventHandler(AddressOf Button1_Click)
' The following line of code is shorthand for the previous line. 
AddHandler Button1.Click, AddressOf Me.Button1_Click

并且还声明:

  

您可以使用在任何地方创建委托的简写方式   编译器可以通过上下文确定委托的类型

因此,在大多数情况下,使用New SomeEventHandlerType(AddessOf x)AddressOf x完成同样的事情。在SQLConnection.StateChange的情况下,事件声明为Public Event StateChange As StateChangeEventHandler,因此编译器知道要使用的正确委托类型,并且AddressOf足够聪明,可以自动为您使用正确的委托类型。不需要使用New StateChangeEventHandler(AddressOf OnConnectionStateChange),但它可以用于代码清晰度,以表明这不是通用的EventHandler委托类型,并且它使用自定义的EventArgs类型。

就取消订阅而言,绝对肯定要避免资源泄漏,您应该在处置订阅者对象之前删除事件处理程序引用。请参阅http://msdn.microsoft.com/en-us/library/ms366768(v=vs.120).aspx说明:

  

为了防止资源泄漏,您应该取消订阅事件   在处理订户对象之前。直到你取消订阅   一个事件,多播委托是该事件的基础   发布对象具有对封装的委托的引用   订阅者的事件处理程序。只要发布对象成立即可   该引用,垃圾收集不会删除您的订阅者   对象

在实际操作中,我发现很少有这样做的例子(即使在MSDN"如何:发布符合.NET Framework指南的事件" http://msdn.microsoft.com/en-us/library/w369ty8x.aspx)。 GC将在最终确定时删除发布者上的事件引用。但是,如果您的发布商的使用寿命比订阅者长得多,则需要确保手动删除事件引用。在SQLConnection示例中,连接对象(即StateChange事件的发布者)的生命周期很短,因此可以说RemoveHandler不需要。有关详情,请参阅此帖子:.NET object events and dispose / GC