2009-10-26 28 views
0

我發現在構造函數中引發的事件(直接在間接引發)不能在該類之外處理。爲了證明這是否是真正的問題,我寫了一個簡單的示例應用程序。VB.NET - 成員事件處理存在問題

類與事件:

Namespace Utils 
    Public Class A 
     Public Event Test() 

     Public Sub New() 
      CallTest() 
     End Sub 

     Public Sub MakeACall() 
      CallTest() 
     End Sub 

     Private Sub CallTest() 
      RaiseEvent Test() 
     End Sub 
    End Class 
End Namespace 

主要形式(處理事件正確):

Public Class Form1 
    Private Sub Button1_Click(ByVal sender As System.Object, _ 
     ByVal e As System.EventArgs) Handles Button1.Click 

     m_A.MakeACall() 
    End Sub 

    Private Sub HandleTest() Handles m_A.Test 
     MsgBox("ta-dah!") 
    End Sub 

    Protected WithEvents m_A As New Utils.A() 
End Class 

主要形式(NOT處理正常事件):

Public Class Form1 
    Private Sub Button1_Click(ByVal sender As System.Object, _ 
     ByVal e As System.EventArgs) Handles Button1.Click 

     m_A = New Utils.A() 
    End Sub 

    Private Sub HandleTest() Handles m_A.Test 
     MsgBox("ta-dah!") 
    End Sub 

    Protected WithEvents m_A As Utils.A 
End Class 

的原因這樣的行爲在寫完這些部分後變得非常明顯,但也許有一種方法可以省略它?

回答

4

這是處理這種情況的可接受模式:

  1. 在EndInit方法進行初始化
  2. 實施ISupportInitialize
  3. 消防您的事件,如果有人試圖使用你的類沒有初始化它引發InvalidOperationException

這是處理這種情況的一種非常普遍的方式,加上串行器也尊重接口。

+0

看起來不錯,謝謝。 – brovar 2009-10-26 14:32:43

1

如果這是一個限於Visual Basic的「問題」,我會感到驚訝;事實是,事件不能從尚未創建的對象中提出。只要你裏面的的構造函數,創建沒有完成。至少,這對我來說是有意義的,而且不管語言如何,似乎都是如此。

不同的編譯器可能會不同意。

但是,所有表單都以相同的方式(Init,Loading等)引發事件的事實表明這與事實非常接近。威爾的答案爲你的問題提供了一個很好的解決方案 - 當它接近它時,根本不是問題:它只是對象工作的方式。

+0

從來沒有真正地給它一個想法,因爲我從來沒有試圖從構造函數中引發事件。我們每天都會學到新的東西;) – brovar 2009-10-26 14:36:27

+1

順便說一下,Microsoft認爲類似的情況是一個錯誤:http://support.microsoft.com/kb/832793 – brovar 2009-10-26 16:58:52