2009-02-11 58 views
3

这是处理事件.NET中的首选/推荐方式:C#中事件处理的首选方法是什么?

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为处理事件而自动创建的。第二种方法对我有什么缺点吗?

回答

8

第一种方式是Microsoft建议的。该模式是:

  1. 一些代码,希望引发一个事件,呼吁OnXxx
  2. OnXxx进行调用以委托
  3. 有线调用事件处理程序

如果执行第二个模型,你可能会忘记base.OnXxx的呼叫并破坏一切。选项2的好处在于,您可以决定是在所有其他事件处理程序之前还是之后调用它。如果你把你的代码放在base.OnXxx之前,你会在事件发生之前执行。当然,第一个模型总是可以使用的,第二个模型只有在你提升事件的子类的时候。

-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在继承链中找到调用正确的实例方法。

+0

你能否再解释一下 - 我不确定我明白你的意思。 – 2009-02-11 16:27:06

5

这完全取决于您想要抓住事件的原因以及原因。

第一种方法(接线)用于当您需要某些其他类来处理事件。你可能需要这样做的原因有很多,另一个类可以访问执行一些复杂逻辑或其他任何事情的服务。重点在于,如果您希望单独的观察员响应该事件,则使用第一种方法。

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

+0

好点,我忘了其他处理事件的其他事情。在表单处理它自己的事件的情况下,为什么VS连接事件处理程序而不是使用保护覆盖? – 2009-02-11 16:23:33

+0

你必须问MS有关这个决定。我不老实地知道。 – 2009-02-11 16:28:17

1

虽然不是原来的问题,我想指出的是:

this.Load += new EventHandler(Form1_Load); 

可以写为:

this.Load += Form1_Load; 

委托建设推断。

0

快速规则并不困难,但这两种方法都存在问题。你选择一个你可以轻松避免的。

代表

很多开发商放置+ =​​代码在一个地方,它可以反复地叫。至少很多新手都这样做。因此,所有者控制所维护的委托列表中将有'n'个条目,并且所有这些条目都会被调用。简单的避免方法是将+ =调用放在只被调用一次的构造函数中。

OnXXXX

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

相关问题