2012-08-07 16 views
0

我有一個基類,一個繼承自基類的中間類和一個繼承自中間類的頂級類。我在基類中定義了一個事件並從一個方法中提取它。我在中間類中爲基類事件定義了一個處理程序,並且在頂級類中也定義了相同的處理程序。 當事件觸發時,中間類處理程序首先被擊中,然後是頂級處理程序。固定的繼承層次結構中的事件處理程序序列是否已修復?

如果我不斷向鏈中添加更多類(超級繼承頂級,超級繼承等等),事件處理程序會不斷在最基本的類中調用(例如,中,頂,超,至尊)。

這個序列總是成立嗎? 如果不是,那麼它會以不同的順序排列?

我正在觀察的順序非常適合這個功能;我只是想確保它會一直工作。

我理解事件並不保證以任何順序觸發,但這是框架在編譯時知道的事情,作爲代碼的作者,我可以說在運行時不會添加/刪除委託這個事件,事件也不會在基地之外消耗,而且是子類連鎖;事實上,它是受保護的。

我不知道幕後發生了什麼,但它可能會在編譯期間設置序列,因此在運行時它已經完成了處理?

編輯:我添加了樣本,以澄清我在做什麼。

Public Class BaseClass 

    Protected Event Hello(ByRef Cancel As Boolean) 

    Public Sub SayHello() 
    Dim Cancel As Boolean 
    RaiseEvent Hello(Cancel) 
    End Sub 

End Class 

Public Class MiddleClass 
    Inherits BaseClass 

    Private Sub MiddleClass_Hello(ByRef Cancel As Boolean) Handles Me.Hello 
    'This appears to always get called first 
    End Sub 

End Class 

Public Class TopClass 
    Inherits MiddleClass 

    Private Sub TopClass_Hello(ByRef Cancel As Boolean) Handles Me.Hello 
    'This appears to always get called second 
    End Sub 

End Class 

Public Class UltraClass 
    Inherits TopClass 

    Private Sub UltraClass_Hello(ByRef Cancel As Boolean) Handles Me.Hello 
    'This appears to always get called third 
    End Sub 

End Class 

'...and so on 
+0

如果您自己重新舉辦活動,並且沒有任何代碼可能會混淆再次提升它的方法,那麼訂單就不會受到干擾。當然,你應該使這種方法是私人的而不是保護,以獲得硬性保證。 – 2012-08-07 17:15:19

+0

@Hans我添加了我的代碼,所以你可以看到一切的範圍。 – toddmo 2012-08-07 17:25:30

回答

1

在您的特定代碼示例中,訂單將按照您的預期行事。

當你有一個標記爲Handles Me....的方法時,VB編譯器所做的一切就是在構造函數的開始處粘貼一個隱藏的AddHandler語句。構造函數從基類型運行到派生類型,因此基類型的隱藏AddHandler將在派生類型中的AddHandler之前運行。 只要你的RaiseEvent在訂單中添加事件處理程序被添加,那麼是的,你會看到你現在看到的訂單。對於像你這樣簡單的VB事件,這種行爲極不可能改變。

觀察我上面的警告:如果事件不是一個簡單的事件,而是一個自定義事件,其中基類可以指定它自己的行爲AddHandler和RaiseEvent,所有投注都關閉。沒有任何東西可以阻止我創建自己的RaiseEvent,它以我想要的任意順序運行處理程序(假設它甚至可以運行它們)!如果Base類不是您擁有的,那麼如果您承擔訂購,我會小心。

通常,具有細微訂購要求的事件處理程序通常會創建難以調試的代碼位。如果可以,最好避免。如果基本派生順序很重要,則可以使用重寫的方法使代碼更加清晰,並且派生類型可以在適當的位置調用MyBase。

+0

謝謝!我擁有基類,這將使我不必記得調用'MyBase.SayHello',再加上我可以使用鼠標來生成方法存根!哈!精彩!我會記得避免在表現不好的情況下訂購要求。 – toddmo 2012-08-08 13:10:55