簡體   English   中英

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

[英]SQLConnection.StateChange Event AddHandler using StateChangeEventHandler vs AddressOf

這兩種為SQLConnection.StateChange事件添加事件處理程序的不同方式有何區別,副作用和/或首選項? 由於AddressOf創建了一個委托( http://msdn.microsoft.com/zh-cn/library/y72ewk2b.aspx ),並且StateChangeEventHandler也是一個委托,所以示例2似乎只是在創建嵌套的委托,但我猜我缺少一些細微差別。

從我的測試來看,使用示例1或2,它們似乎都可以正常工作。嘗試多次調用AddHandler時,都不會引發異常(我的第一個假設是,如果再次嘗試調用AddHandler,則調用示例#1會引發錯誤。因為它將添加相同的引用,而示例2不會添加示例,因為它將是一個新的委托實例;但是,它們都將成功,沒有例外)。

示例1:僅使用AddressOfhttp : //msdn.microsoft.com/zh-cn/library/7taxzxka.aspx

AddHandler conn.StateChange, AddressOf OnConnectionStateChange

示例2:使用下面列出的StateChangeEventHandler委托的實例: http : //msdn.microsoft.com/zh-cn/library/a0hee08w( StateChangeEventHandler .aspx? StateChangeEventHandler = vb#code-snippet-2

AddHandler conn.StateChange, New StateChangeEventHandler(AddressOf OnConnectionStateChange)

另外,是否需要在通過RemoveHandler /結束using塊之前刪除此處理程序,或者SQLConnection.Dispose會為您解決這個問題? 我不確定如果從MSDN站點在下面的示例2中使用StateChangeEventHandler ,那么如何刪除事件處理程序,因為StateChangeEventHandler委托的實例未存儲在本地變量中,因此您沒有要刪除的處理程序的引用(您必須執行與示例4類似的操作)。

示例3:僅使用AddressOf 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

Example#4:使用StateChangeEventHandler RemoveHandler

    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);

connection.StateChange  += OnStateChange;

我偶然發現了這篇文章( 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 ,將其聲明為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/zh-cn/library/w369ty8x .aspx )。 最終確定時,GC將負責刪除發布者上的事件引用。 但是,如果存在發布者的壽命比訂閱者更長的場景,則需要確保手動刪除事件引用。 在SQLConnection示例中,連接對象(即StateChange事件的發布者)的生存期很短,因此可以說不需要RemoveHandler 有關更多詳細信息,請參見這篇文章: .NET對象事件和處理/ GC

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM