事件设计

更新:2007 年 11 月

事件是操作发生时允许执行特定于应用程序的代码的机制。事件要么在相关联的操作发生前发生(事前事件),要么在操作发生后发生(事后事件)。例如,当用户单击窗口中的按钮时,将引发一个事后事件,以允许执行特定于应用程序的方法。 事件处理程序委托会绑定到系统引发事件时要执行的方法。事件处理程序会添加到事件中,以便当事件引发时,事件处理程序能够调用它的方法。事件可以具有特定于事件的数据,例如,按下鼠标事件可以包含有关屏幕光标位置的数据。

事件处理方法的签名与事件处理程序委托的签名是相同的。事件处理程序签名遵循下面的约定:

  • 返回类型为 Void

  • 第一个参数命名为 sender,是 Object 类型。它是引发事件的对象。

  • 第二个参数命名为 e,是 EventArgs 类型或 EventArgs 的派生类。它是特定于事件的数据。

  • 该方法有且仅有两个参数。

有关事件的更多信息,请参见 处理和引发事件

使用 System.EventHandler<T>,而不要手动创建用作事件处理程序的新委托。

此准则主要适用于新的功能区域。如果您是在已经使用非泛型事件处理程序的区域中扩展功能,则可以继续使用非泛型事件处理程序,以保持设计一致。

如果您的库针对的是不支持泛型的 .NET Framework 版本,则无法遵循此准则。

考虑使用 System.EventArgs 的派生类作为事件参数,除非您完全确定事件决不会需要向事件处理方法传递任何数据(这种情况下可以直接使用 System.EventArgs 类型)。

如果您定义的事件采用 EventArgs 实例而不是您定义的派生类,则不能够在以后的版本中向该事件添加数据。出于上述原因,建议创建一个空的 EventArgs 派生类。这使您能够在以后的版本中在不引入重大更改的情况下向事件添加数据。

使用受保护的虚方法来引发每个事件。这只适用于未密封类的非静态事件,而不适用于结构、密封类或静态事件。

遵循此准则可使派生类能够通过重写受保护的方法来处理基类事件。受保护的 virtual(在 Visual Basic 中是 Overridable)方法的名称应该是为事件名加上 On 前缀而得到的名称。例如,名为“TimeChanged”的事件的受保护的虚方法被命名为“OnTimeChanged”。

ms229011.alert_caution(zh-cn,VS.90).gif重要说明:

重写受保护的虚方法的派生类无需调用基类实现。即使没有调用基类的实现,基类也必须继续正常工作。

使用一个参数,该参数已类型化为引发事件的受保护方法的事件参数类。该参数应命名为 e。

FontDialog 类提供下面的方法,该方法引发 Apply 事件:

Protected Overridable Sub OnApply( ByVal e As EventArgs )
protected virtual void OnApply(EventArgs e);

当引发非静态事件时,不要将 null(在 Visual Basic 中为 Nothing)作为 sender 参数进行传递。

对于静态事件,sender 参数应该为 null(在 Visual Basic 中是 Nothing)。

当引发事件时,不要将 null(在 Visual Basic 中为 Nothing)作为事件数据参数进行传递。

如果没有事件数据,则传递 Empty,而不要传递 null。

事件处理方法中会发生任意代码执行,对此一定要做好准备。

考虑将引发事件的代码放置在 try-catch 块中,以防止由事件处理程序引发的未处理异常所导致的程序终止。

考虑引发最终用户可以取消的事件。这仅适用于事前事件。

如果您正在设计可取消的事件,请使用 CancelEventArgs(而非 EventArgs)作为事件数据对象 e 的基类。

部分版权所有 2005 Microsoft Corporation。保留所有权利。

部分版权所有 Addison-Wesley Corporation。保留所有权利。

有关设计指南的更多信息,请参见 Krzysztof Cwalina 和 Brad Abrams 编著、Addison-Wesley 于 2005 年出版的“Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries”(《框架设计指南:可重用 .NET 库的约定、术语和模式》)。

请参见

概念

自定义事件处理程序设计

其他资源

成员设计准则

类库开发的设计准则