委托和事件处理程序的区别

3

我很好奇简单的事件处理程序到底有什么用处。

我可以有以下代码:

event EventHandler blah;

或者

delegate void Blah();
event Blah Blah1;

除了节省一行代码之外,使用事件处理程序有什么优点吗?

一个 EventHandler 只是一个设计,一个 Microsoft、System.ComponentModel 的东西(尽管我相信 EventHandler 委托驻留在 System 命名空间中)。它的使用是一种模式,在 .NET Framework BCL(基类库)中随处可见。 - John Leidegren
2个回答

7
一个 EventHandler 是一个带有几个额外参数的 delegate。第一个参数是发送者,也就是引起事件的对象,第二个参数是额外的事件数据。这是一种声明事件非常有用的一致模式。如果不将发送者作为参数传递,你将无法轻松地检测到哪个对象引起了事件,这可能会导致不必要的重复(复制和粘贴)代码。如果遵循标准的事件模式,你的事件处理程序可以根据引起事件的对象的属性执行不同的任务。
此外,有些事件会携带额外的信息,例如类型为 MouseEventHandler 的事件将在其第二个参数 (MouseEventArgs) 中传递鼠标指针的位置供你的事件处理程序使用。这种模式的好处是,如果你的事件处理程序是通用的并且不需要它,你可以忽略辅助数据。例如,你可以将具有 EventHandler 签名的方法连接到 MouseEventHandler 事件上(因为第二个参数的类型继承自 EventArgs)。

3

您的委托不会提供任何有关触发事件的指示 - 没有与“sender”相当的东西。

此外,如果您使用以下签名实现处理程序:

void Handler(object sender, EventArgs e)

然后,由于委托的变化,它可以处理任何遵循正常模式的事件。因此,即使您不需要来自事件参数的任何信息,您仍然可以订阅(例如)Control.KeyPress事件。
现在,如果所有事件都遵循相同的模式,则可以使用一个处理程序来处理多个事件 - 但是您无法将其用于处理具有委托类型Action的事件(这基本上是您的委托类型对应的内容 - 没有必要声明一个新的)。
编辑:鉴于您的评论,我觉得我应该指出,您的问题实际上并没有涵盖事件和委托之间的区别 - 它涵盖了在事件中使用“标准”委托类型和在事件中使用“自定义”委托类型之间的区别。委托和事件之间的区别实际上是关于封装。我有一篇文章,您可能会发现有用 - 尽管它主要涵盖了与C#深入相同的内容。

对于额外的信息,如果您在运行时使用共享处理程序动态添加控件(例如添加按钮/菜单项),则sender特别有用。您可以使用发送器获取项目,然后(通常)使用项目上的Tag获取任何其他信息。 - Marc Gravell
@Jon - 这实际上是《C#深入》中让我感到困惑的事情之一。您指出委托和事件之间的区别很重要,但尽管我已经多次阅读该部分,我仍然不明白为什么这种区别很重要。我认为您在这里的回答填补了谜题的一部分。 - David Hall

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接