Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用StateChangeEventHandler与AddressOf的SQLConnection.StateChange事件AddHandler_C#_.net_Vb.net_Events_Event Handling - Fatal编程技术网

C# 使用StateChangeEventHandler与AddressOf的SQLConnection.StateChange事件AddHandler

C# 使用StateChangeEventHandler与AddressOf的SQLConnection.StateChange事件AddHandler,c#,.net,vb.net,events,event-handling,C#,.net,Vb.net,Events,Event Handling,为SQLConnection.StateChange事件添加事件处理程序的这两种不同方法的区别、副作用和/或首选项是什么?由于AddressOf创建了一个委托,而StateChangeEventHandler也是一个委托,所以示例2似乎只是在创建嵌套委托,但我猜我缺少一些细微差别 根据我的测试,使用示例1或示例2,它们的工作方式似乎相同。当尝试多次调用AddHandler时不会引发异常我的第一个假设是,如果第二次尝试调用AddHandler,调用示例1会引发错误,因为它将添加相同的引用,而示例2

为SQLConnection.StateChange事件添加事件处理程序的这两种不同方法的区别、副作用和/或首选项是什么?由于AddressOf创建了一个委托,而StateChangeEventHandler也是一个委托,所以示例2似乎只是在创建嵌套委托,但我猜我缺少一些细微差别

根据我的测试,使用示例1或示例2,它们的工作方式似乎相同。当尝试多次调用AddHandler时不会引发异常我的第一个假设是,如果第二次尝试调用AddHandler,调用示例1会引发错误,因为它将添加相同的引用,而示例2不会,因为它将是一个新的委托实例;然而,他们都毫无例外地取得了成功

示例1:仅使用以下地址:

示例2:使用StateChangeEventHandler委托的实例,如下所示:

另外,是否需要在通过RemoveHandler处理/结束使用块之前删除此处理程序,或者SQLConnection.dispose会为您解决这个问题?如果在MSDN站点中使用下面示例2中的StateChangeEventHandler,我不确定您将如何删除事件处理程序,因为StateChangeEventHandler委托的实例未存储在局部变量中,因此您没有要删除的处理程序的引用,您必须执行类似于示例4的操作

示例3:仅使用AddressOf移除处理程序

示例4:使用StateChangeEventHandler移除处理程序

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

connection.StateChange  += new StateChangeEventHandler(OnStateChange);
vs


我偶然发现了这篇文章,其中提到AddressOf只是新EventHandlerAddressOf 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
它还指出:

您可以使用快捷方式在任何位置创建代理 编译器可以通过上下文确定委托的类型

因此,在大多数情况下,使用新的SomeEventHandlerTypeAddesof x或仅使用AddressOf x可以完成相同的事情。在SQLConnection.StateChange的情况下,事件被声明为公共事件StateChange作为StateChangeEventHandler,因此编译器知道要使用的正确委托类型,AddressOf足够智能,可以自动为您使用正确的委托类型。无需使用新的StateChangeEventHandlerAddressOf OnConnectionStateChange,但为了代码清晰起见,可以使用它来显示这不是泛型EventHandler委托类型,而是使用自定义EventArgs类型

至于取消订阅,为了绝对避免资源泄漏,您应该在处理订阅对象之前删除事件处理程序引用。请参见哪些国家:

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

在实际操作中,即使在MSDN How to:Publish事件中,我也很少看到符合.NET Framework准则的示例。当发布服务器最终确定时,GC将负责删除发布服务器上的事件引用。但是,如果您遇到发布服务器的寿命比订阅服务器长得多的情况,则需要确保手动删除事件引用。在SQLConnection示例中,连接对象(即StateChange事件的发布者)的生存期很短,因此RemoveHandler可以说是不需要的。有关更多详细信息,请参阅本文:

    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
    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);
connection.StateChange  += OnStateChange;
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