SQLConnection.StateChange事件AddHandler使用StateChangeEventHandl

本文关键字:使用 StateChangeEventHandl AddHandler 事件 StateChange SQLConnection | 更新日期: 2023-09-27 18:02:32

SQLConnection.StateChange事件添加事件处理程序的这两种不同方式的区别、副作用和/或首选项是什么?因为AddressOf创建了一个委托(http://msdn.microsoft.com/en-us/library/y72ewk2b.aspx), StateChangeEventHandler也是一个委托,例2似乎只是创建嵌套委托,但我猜有一些细微差别,我错过了。

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

示例1:仅使用AddressOf: http://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)

此外,是否需要在通过RemoveHandler处置/结束using块之前删除此处理程序,或者SQLConnection.Dispose将为您处理此处理程序?我不确定如何从MSDN站点使用下面示例#2中的StateChangeEventHandler来删除事件处理程序,因为StateChangeEventHandler委托的实例没有存储在本地变量中,所以您没有要删除的处理程序的引用(您必须做类似于示例#4的事情)。

示例#3: RemoveHandler仅使用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
示例#4: RemoveHandler使用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

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

connection.StateChange  += new StateChangeEventHandler(OnStateChange);

vs。

connection.StateChange  += OnStateChange;

SQLConnection.StateChange事件AddHandler使用StateChangeEventHandl

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

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),但它可以用于代码清晰,以显示这不是通用的eventandler委托类型,并且它使用自定义EventArgs类型。

至于取消订阅,为了绝对确保避免资源泄漏,您应该在处置订阅者对象之前删除事件处理程序引用。请参阅http://msdn.microsoft.com/en-us/library/ms366768(v=vs.120).aspx,其中声明:

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

在实际实践中,我很少看到这样做的例子(即使在MSDN"如何:发布符合。net框架指南的事件"http://msdn.microsoft.com/en-us/library/w369ty8x.aspx中)。当完成时,GC将负责删除发布者上的事件引用。但是,如果在某些情况下,发布者订阅者存活的时间要长得多,则需要确保手动删除事件引用。在SQLConnection示例中,连接对象(即StateChange事件的发布者)的生命周期很短,因此可以说不需要RemoveHandler。.NET对象事件和dispose/GC