Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/329.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#中事件处理的首选方法是什么?_C#_Winforms_Event Handling - Fatal编程技术网

C#中事件处理的首选方法是什么?

C#中事件处理的首选方法是什么?,c#,winforms,event-handling,C#,Winforms,Event Handling,在.NET中处理事件的首选/推荐方法是: this.Load += new EventHandler(Form1_Load); private void Form1_Load(object sender, EventArgs e) { } 或 protected override void OnLoad(EventArgs e) { base.OnLoad(e); } 每种方法的优缺点是什么?多年来,我一直在使用这两种方法,通常更倾向于使用第一种方法,因为VisualStudio会自

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

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

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

每种方法的优缺点是什么?多年来,我一直在使用这两种方法,通常更倾向于使用第一种方法,因为VisualStudio会自动创建用于处理事件的方法。但是,第二个方法是否有我所缺少的好处?

重写的方法更可取,因为它将被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
是更好的实现,原因如下<代码>条形图必须按照以下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)

我们必须为handling方法创建一个委托,
EventHandler
的一个实例,然后在基类中对事件调用
add\u Changed
方法。虽然这些都不是性能杀手,
Baz
工作不需要前面的代码。由于对OnChanged的
的任何调用都是虚拟的,因此唯一的性能损失将是CLR在继承链中找到要调用的正确实例方法。

这完全取决于您希望捕获事件的位置和原因

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


第二种方法(重写)用于希望窗体响应的时间,因为它可以;因为它的责任是地方性的

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

  • 一些代码想要引发一个事件,调用OnXxx
  • OnXxx向代表打电话
  • 调用有线事件处理程序

  • 如果执行第二个模型,您可能会忘记base.OnXxx调用并破坏一切。选项2很好的一部分是,您可以决定是在所有其他事件处理程序之前还是之后调用您。如果将代码放在base.OnXxx之前,则会在事件执行之前执行。当然,第一个模型总是可以使用的,第二个模型只有在对引发事件的类进行子类化时才可以使用。

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

    this.Load += new EventHandler(Form1_Load);
    
    可以写为:

    this.Load += Form1_Load;
    

    代理结构是推断出来的。

    没有硬性规定,但这两种方法都有缺陷。你可以选择一个你可以很容易避免的

    代表

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

    OnXXXX


    风险在于忘记调用base.XXX方法。这是一个常见的bug源,如果您没有调用基类版本,大多数Windows程序员都会意识到问题所在——这对于Windows消息(paint等)来说尤其如此

    说得好,我忘了处理事件的其他事情。在窗体处理它自己的事件的情况下,为什么VS连接事件处理程序而不是使用受保护的重写?您必须询问MS关于该决定的问题。我真的不知道。你能进一步解释一下吗?我不确定我是否理解你的意思。@DK:风格问题。我更喜欢“这个”,但很多人不喜欢,这很好。