如何正确覆盖引发事件的方法

时间:2012-07-11 11:29:08

标签: .net vb.net events inheritance override

我有一个MyCol类,它继承自ObservableCollection(Of T)。它以这种方式覆盖InsertItem方法:

Public Event PreInsertItem As EventHandler(Of EventArgs)

Protected Overridable Sub OnPreInsertItem(e As EventAtgs)
    RaiseEvent PreInsertItem(Me, e)
End Sub

Protected Overrides Sub InsertItem(index As Integer, item As T)
    OnPreInsertItem(EventArgs.Empty)

    MyBase.InsertItem(index, item)
End Sub

正如您所看到的,我添加了一个事件,每次将项目添加到MyCol集合时都会引发该事件。

接下来,我创建另一个继承自MyCol的类MyColSubClass,并重写InsertItem方法:

Public Overrides Sub InsertItem(index as Integer, item as T)
    OnPreInsertItem(EventArgs.Empty)

    ' some additional code goes here

    MyBase.InsertItem(index, item)
End Sub

问题:

现在,当我使用MyColSubClass的一个实例并添加一个项目时, PreInsertItem 事件被引发两次:首先在MyColSubClass中,而不是在MyCol中。

我应该使用什么样的设计模式来使PreInsertItem事件只引发一次:在MyColSubClass中?

N.B。

示例中显示的类和事件从实际应用程序中简化,但假设它们显示了确切的应用程序结构。在最后一个继承的类中引发事件是必须的。

3 个答案:

答案 0 :(得分:1)

如果你确定基类会引发事件,那么在派生类中这样做是没用的。

只需将覆盖更改为:

Public Overrides Sub InsertItem(index as Integer, item as T)
    ' some additional code goes here

    MyBase.InsertItem(index, item)
End Sub

那应该没事。

但是如果你改变你的派生方法,并且停止调用MyBase.InsertItem(...),你应该在你的覆盖中引发事件以确保它被引发:

Public Overrides Sub InsertItem(index as Integer, item as T)
    ' some additional code goes here

    OnPreInsertItem(EventArgs.Empty)

    ' insert your item and do whatever...
End Sub

修改

如果您需要更改引发事件的方式,但想确保它只被引发一次,只需覆盖派生类中的OnPreInsertItem方法:

Protected Overrides Sub OnPreInsertItem(e as EventArgs)
    ' Do wahetever you need here, change e, add info, whatever...
    ' ...
    ' Then raise the event (or call MyBase.OnPreInsertItem, as you like)
    RaiseEvent PreInsertItem(Me, e)
End Sub

Public Overrides Sub InsertItem(index as Integer, item as T)
    ' some additional code goes here

    ' This will work only if MyBase.InsertItem calls OnPreInsertItem. 
    ' Otherwise, you have to handle the insertion and raise the event
    ' yourself without calling the base method.
    MyBase.InsertItem(index, item)
End Sub

由于OnPreInsertItem是可覆盖的,因此当您在派生类中插入项时,将调用派生类中的版本。

希望有所帮助:)

答案 1 :(得分:0)

我认为你不应该在你的子类MyColSubClass中提出OnPreInsertItem 你的方法应该是这样的:

Public Overrides Sub InsertItem(index as Integer, item as T)
    ' some additional code goes here

    MyBase.InsertItem(index, item)
End Sub

您正在扩展基类的某些功能。 如果要替换该特定功能,则您的方法应如下所示:

Public Overrides Sub InsertItem(index as Integer, item as T)
    OnPreInsertItem(EventArgs.Empty)

    ' some additional code goes here

End Sub

您可以找到更多信息herehere

答案 2 :(得分:0)

如果我做得对,你想在不同的继承级别上向EventArg类添加信息。在这种情况下,提供与事件get get相同级别的EventArg成员在我看来是最好的解决方案,而InsertItem()的所有覆盖只是修改此EventArg成员事件以及此事件仅在最高可能的情况下被提升水平。