14

什么时候应该做以下事情?

class Foo : Control
{
    protected override void OnClick(EventArgs e)
    {
        // new code here
    }
}

与此相反?

class Foo : Control
{
    public Foo()
    {
        this.Click += new EventHandler(Clicked);
    }

    private void Clicked(object sender, EventArgs e)
    {
        // code
    }
}
4

7 回答 7

9

覆盖而不是附加委托会产生更高效的代码,因此通常建议您尽可能始终这样做。有关详细信息,请参阅此 MSDN 文章。这是一个相关的报价:

受保护的 OnEventName 方法还允许派生类在不附加委托的情况下覆盖事件。派生类必须始终调用基类的 OnEventName 方法,以确保注册的委托接收事件。

于 2008-10-01T19:37:05.443 回答
8

该事件适用于外部订阅者。当您派生某些控件时,请始终覆盖 OnEvent 方法,而不是订阅事件。这样,您可以确定何时调用您的代码,因为实际事件是在您调用 base.OnEvent() 时触发的,您可以在代码之前、代码之后、代码中间或不在代码中调用它全部。然后,您还可以对事件的返回值做出反应(即 EventArgs 对象中更改的属性)。

于 2008-10-01T19:38:38.623 回答
3

Be aware that (at least in .NET 2.0) I have found a few places in the framework (specifically in the DataTable class) where the OnFoo method is only called when the corresponding Foo event has been handled! This contravenes the framework design guidelines but we're stuck with it.

I've gotten around it by handling the event with a dummy handler somewhere in the class, eg:

public class MyDataTable : DataTable
{
    public override void EndInit()
    {
        base.EndInit();
        this.TableNewRow += delegate(object sender, DataTableNewRowEventArgs e) { };
    }

    protected override void OnTableNewRow(DataTableNewRowEventArgs e)
    {
        base.OnTableNewRow(e);
        // your code here
    }
}
于 2008-10-01T22:25:57.473 回答
1

订阅事件的目的是让控件监视不同控件上的事件。对于监视您自己的事件 OnClick 很好。但是请注意,Control.OnClick 会处理触发那些订阅的事件,因此请务必在您的覆盖中调用它。

于 2008-10-01T19:40:00.710 回答
0

如果您像 Kent Boogaart 评论一样覆盖,您需要小心回调 base.OnClick 以允许调用事件订阅

于 2008-10-01T19:38:53.053 回答
0

继承的类不应该订阅它自己的事件,或者它的基类的事件。

现在,如果一个类中有另一个不同的类的实例,那么它可以使用该类的事件,并确定它是否应该引发它自己的事件。

例如,我最近推出了一个 MRU List 课程。其中有许多 ToolStripMenuItem 控件,我使用了它们的单击事件。在那个点击事件被消耗之后,我然后提出了我班级的事件。(请参阅此处的源代码

于 2008-10-01T19:39:43.003 回答
0

值得注意的是,在某些极端情况下,它仅适用于处理程序而不适用于 OnEvent 覆盖。一个这样的例子——

为什么在 WPF 中删除 StartupUri 时不应用样式?

于 2019-09-19T21:09:59.387 回答