事件教程
本教程展示如何在 C# 中声明事件、调用事件和挂接到事件。
本教程展示如何在 C# 中声明事件、调用事件和挂接到事件。
示例文件
请参见“事件”示例以下载和生成本教程中所讨论的示例文件。
请参见“事件”示例以下载和生成本教程中所讨论的示例文件。
其他阅读材料
event
delegate
处理和引发事件
委托教程
Windows 窗体中事件处理程序的介绍
教程
C# 中的“事件”是当对象发生某些有趣的事情时,类向该类的客户提供通知的一种方法。事件最常见的用途是用于图形用户界面;通常,表示界面中的控件的类具有一些事件,当用户对控件进行某些操作(如单击某个按钮)时,将通知这些事件。
event
delegate
处理和引发事件
委托教程
Windows 窗体中事件处理程序的介绍
教程
C# 中的“事件”是当对象发生某些有趣的事情时,类向该类的客户提供通知的一种方法。事件最常见的用途是用于图形用户界面;通常,表示界面中的控件的类具有一些事件,当用户对控件进行某些操作(如单击某个按钮)时,将通知这些事件。
但是事件未必只用于图形界面。事件为对象提供一种通常很有用的方法来发出信号表示状态更改,这些状态更改可能对该对象的客户很有用。事件是创建类的重要构造块,这些类可在大量的不同程序中重复使用。
使用委托来声明事件。如果您尚未学习“委托教程”,您应先学习它,然后再继续。请回忆委托对象封装一个方法,以便可以匿名调用该方法。事件是类允许客户为其提供方法(事件发生时应调用这些方法)的委托的一种方法。事件发生时,将调用其客户提供给它的委托。
除声明事件、调用事件和与事件挂钩的示例以外,本教程还介绍下列主题:
事件和继承
接口中的事件
.NET Framework 指南
示例 1
下面的简单示例展示一个 ListWithChangedEvent 类,该类类似于标准的 ArrayList 类,而且,每当列表内容更改时,该类均调用 Changed 事件。这样一个通用用途的类可在大型程序中以多种方式使用。
接口中的事件
.NET Framework 指南
示例 1
下面的简单示例展示一个 ListWithChangedEvent 类,该类类似于标准的 ArrayList 类,而且,每当列表内容更改时,该类均调用 Changed 事件。这样一个通用用途的类可在大型程序中以多种方式使用。
例如,某字处理器可能包含打开的文档的列表。每当该列表更改时,可能需要通知字处理器中的许多不同对象,以便能够更新用户界面。使用事件,维护文档列表的代码不需要知道需要通知谁,一旦文档列表发生了更改,将自动调用该事件,正确通知每个需要通知的对象。使用事件提高了程序的模块化程度。


































































































输出
This is called when the event fires.
This is called when the event fires.
代码讨论
声明事件 若要在类内声明事件,首先必须声明该事件的委托类型(如果尚未声明的话)。
public delegate void ChangedEventHandler(object sender, EventArgs e);
委托类型定义传递给处理该事件的方法的一组参数。多个事件可共享相同的委托类型,因此仅当尚未声明任何合适的委托类型时才需要执行该步骤。
This is called when the event fires.
This is called when the event fires.
代码讨论
声明事件 若要在类内声明事件,首先必须声明该事件的委托类型(如果尚未声明的话)。
public delegate void ChangedEventHandler(object sender, EventArgs e);
委托类型定义传递给处理该事件的方法的一组参数。多个事件可共享相同的委托类型,因此仅当尚未声明任何合适的委托类型时才需要执行该步骤。
接下来,声明事件本身。
public event ChangedEventHandler Changed;
声明事件的方法与声明委托类型的字段类似,只是关键字 event 在事件声明前面,在修饰符后面。事件通常被声明为公共事件,但允许任意可访问修饰符。
声明事件的方法与声明委托类型的字段类似,只是关键字 event 在事件声明前面,在修饰符后面。事件通常被声明为公共事件,但允许任意可访问修饰符。
调用事件 类声明了事件以后,可以就像处理所指示的委托类型的字段那样处理该事件。如果没有任何客户将委托与该事件挂钩,该字段将为空;否则该字段引用应在调用该事件时调用的委托。因此,调用事件时通常先检查是否为空,然后再调用事件。
if (Changed != null)
Changed(this, e);
调用事件只能从声明该事件的类内进行。
if (Changed != null)
Changed(this, e);
调用事件只能从声明该事件的类内进行。
与事件挂钩 从声明事件的类外看,事件像个字段,但对该字段的访问是非常受限制的。只可进行如下操作:
在该字段上撰写新的委托。
从字段(可能是复合字段)移除委托。
使用 += 和 -= 运算符完成此操作。为开始接收事件调用,客户代码先创建事件类型的委托,该委托引用应从事件调用的方法。然后它使用 += 将该委托写到事件可能连接到的其他任何委托上。
在该字段上撰写新的委托。
从字段(可能是复合字段)移除委托。
使用 += 和 -= 运算符完成此操作。为开始接收事件调用,客户代码先创建事件类型的委托,该委托引用应从事件调用的方法。然后它使用 += 将该委托写到事件可能连接到的其他任何委托上。
// Add "ListChanged" to the Changed event on "List":
List.Changed += new ChangedEventHandler(ListChanged);
当客户代码完成接收事件调用后,它将使用运算符 -= 从事件移除其委托。
List.Changed += new ChangedEventHandler(ListChanged);
当客户代码完成接收事件调用后,它将使用运算符 -= 从事件移除其委托。
// Detach the event and delete the list:
List.Changed -= new ChangedEventHandler(ListChanged);
事件和继承
当创建可以从中派生的通用组件时,事件中有时出现似乎会成为问题的情况。由于事件只能从声明它们的类中调用,因此派生类不能直接调用在基类内声明的事件。虽然这有时符合需要,但通常使派生类能够自由调用事件更合适。这通常通过为事件创建受保护的调用方法来实现。通过调用该调用方法,派生类便可以调用此事件。为获得更大的灵活性,调用方法通常声明为虚拟的,这允许派生类重写调用方法。这使得派生类可以截获基类正在调用的事件,有可能对这些事件执行它自己的处理。
List.Changed -= new ChangedEventHandler(ListChanged);
事件和继承
当创建可以从中派生的通用组件时,事件中有时出现似乎会成为问题的情况。由于事件只能从声明它们的类中调用,因此派生类不能直接调用在基类内声明的事件。虽然这有时符合需要,但通常使派生类能够自由调用事件更合适。这通常通过为事件创建受保护的调用方法来实现。通过调用该调用方法,派生类便可以调用此事件。为获得更大的灵活性,调用方法通常声明为虚拟的,这允许派生类重写调用方法。这使得派生类可以截获基类正在调用的事件,有可能对这些事件执行它自己的处理。
在前面的示例中,这已用 OnChanged 方法实现。如果需要,派生类可调用或重写该方法。
接口中的事件
事件和字段之间的另一个差异是,事件可放在接口中,而字段不能。当实现接口时,实现类必须在实现接口的类中提供相应的事件。
事件和字段之间的另一个差异是,事件可放在接口中,而字段不能。当实现接口时,实现类必须在实现接口的类中提供相应的事件。
.NET Framework 指南
尽管 C# 语言允许事件使用任意委托类型,但“.NET Framework”对于应为事件使用的委托类型有一些更严格的指南。如果打算将您的组件与“.NET Framework”一起使用,您可能希望遵守这些指南。
尽管 C# 语言允许事件使用任意委托类型,但“.NET Framework”对于应为事件使用的委托类型有一些更严格的指南。如果打算将您的组件与“.NET Framework”一起使用,您可能希望遵守这些指南。
“.NET Framework”指南指示用于事件的委托类型应采用两个参数:指示事件源的“对象源”参数和封装事件的其他任何相关信息的“e”参数。“e”参数的类型应从 EventArgs 类派生。对于不使用其他任何信息的事件,“.NET Framework”已定义了一个适当的委托类型:EventHandler。
示例 2
下面的示例是“示例 1”的修改版本,它遵守“.NET Framework”指南。该示例使用 EventHandler 委托类型。
下面的示例是“示例 1”的修改版本,它遵守“.NET Framework”指南。该示例使用 EventHandler 委托类型。































































































输出
This is called when the event fires.
This is called when the event fires.
This is called when the event fires.
This is called when the event fires.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现