3

这是在 .NET 中处理事件的首选/推荐方式:

this.Load += new EventHandler(Form1_Load);
private void Form1_Load(object sender, EventArgs e)
{ }

或者

protected override void OnLoad(EventArgs e)
{
    base.OnLoad(e);
}

每种方法的优缺点是什么?多年来我一直使用这两种方法,并且通常更倾向于第一种方法,因为这是 Visual Studio 自动创建的用于处理事件的方法。我缺少的第二种方法有什么好处吗?

4

5 回答 5

8

第一种方法是微软建议的。模式是:

  1. 一些代码想要引发一个事件,调用 OnXxx
  2. OnXxx 调用代理
  3. 调用有线事件处理程序

如果您执行第二个模型,您可能会忘记 base.OnXxx 调用并破坏所有内容。选项 2 的优点是您可以决定是在所有其他事件处理程序之前还是之后调用您。如果您将代码放在 base.OnXxx 之前,您会在事件发生之前被执行。当然,第一个模型总是可以使用的,第二个模型只有在你继承引发事件的类时才可以使用。

于 2009-02-11T16:21:40.627 回答
5

这完全取决于您想在哪里捕捉事件以及为什么。

第一种方法(连线)用于当您希望其他类处理事件时。出于多种原因,您可能需要这样做;另一个类可能有权访问执行某些复杂逻辑或其他什么的服务。关键是当您希望单独的观察者响应事件时使用第一种方法。

第二种方法(覆盖)用于当您希望表单响应时,因为它可以;因为它的责任是本地的。

于 2009-02-11T16:20:04.220 回答
1

虽然不是最初的问题,但我想指出:

this.Load += new EventHandler(Form1_Load);

可以写成:

this.Load += Form1_Load;

推断委托构造。

于 2009-02-11T16:31:48.683 回答
0

没有硬性规定,但两种方法都有陷阱。你选择一个你可以轻松避免的。

代表们

许多开发人员将 += 代码放在可以重复调用的地方。至少很多新手都会这样做。因此,所有者控件维护的委托列表中将有“n”个条目,并且所有条目都被调用。避免的简单方法是将 += 调用放在构造函数类型的地方,它只被调用一次。

OnXXXX

风险在于忘记调用 base.XXX 方法。这是错误的常见来源,如果您错过调用基类版本,大多数 Windows 程序员都会意识到这些问题 - 这对于 Windows 消息(绘制等)的情况尤其如此。

于 2009-02-11T16:46:26.637 回答
-1

重写的方法是可取的,因为它将被调用多态的几乎由CLR。

[编辑] 这就是为什么我认为重写方法更可取的原因:

这是一个简单的例子:

class Foo
{
    public event EventHandler Changed = delegate { };

    protected virtual void OnChanged()
    {
        this.Changed(this, EventArgs.Empty);
    }
}

class Bar : Foo
{
    public Bar()
    {
        this.Changed += new EventHandler(this.Bar_Changed);
    }

    void Bar_Changed(Object sender, EventArgs e) { }
}

class Baz : Foo
{
    protected override void OnChanged() 
    { 
        base.OnChanged();
    }
}

现在我相信这Baz是更好的实现,这就是原因。 Bar必须执行以下 IL 指令来连接事件:

    L_000a: ldftn instance void Bar::Bar_Changed(object, class [mscorlib]System.EventArgs)
    L_0010: newobj instance void [mscorlib]System.EventHandler::.ctor(object, native int)
    L_0015: call instance void Foo::add_Changed(class [mscorlib]System.EventHandler)

我们必须创建一个委托来处理方法,一个实例EventHandler然后add_Changed在基类中调用事件上的方法。虽然这些不是性能杀手,但之前的代码都不需要Baz工作。由于任何调用OnChanged都是虚拟的,唯一的性能损失将是 CLR 在继承链中找到正确的实例方法来调用。

于 2009-02-11T16:17:19.390 回答