什么是事件?
事件是类的一种成员。如果类型定义了事件,那么它就可以通知其它对象发生了特定的事情(比如Button的Click事件)。事件是实现这种交互的类型成员。
事件是建立在委托的基础之上,事件是被封装的委托。
一,发布者和订阅者模式
理解这幅图对于理解事件的原理非常重要:
1,发布者类订义了事件成员。
2,订阅者类注册在事件成员被触发时要调用的方法(事件处理程序)。
3,当发布者触发事件时,所有列表中的事件处理程序都会被调用。
二,实际案例
这是一个电子邮件到达通知的例子,当电子邮件到达时,会引发NewMail事件,而注册到这个事件上的Fax和Pager都会收到通知,并以自己的方式处理该邮件。
代码如下:
namespace EventDemo2 { class Program { static void Main(string[] args) { MailManager mm = new MailManager(); Fax fax = new Fax(mm); Pager pager = new Pager(mm); mm.SimulateNewMail("A","B","Hi,how are you?"); Console.WriteLine(); Console.WriteLine("********Pager undo register********"); pager.Unregister(mm); mm.SimulateNewMail("B", "A", "I'm fine,and you?"); Console.ReadKey(); } } //发布者类 internal class MailManager { //1,声明事件 public event EventHandler<NewMailEventArgs> NewMail; //2,触发事件1-引发事件的方法 protected virtual void OnNewMail(NewMailEventArgs e) { if (NewMail != null) { NewMail(this,e); } } //3,触发事件2-将输入转化为期望事件 public void SimulateNewMail(string from, string to, string subject) { NewMailEventArgs e = new NewMailEventArgs(from,to,subject); OnNewMail(e); } } //自定义类,通过扩展EventArgs来传递数据 //这里容纳发送给事件接受者的信息 internal class NewMailEventArgs : EventArgs { private readonly string _from, _to, _subject; public NewMailEventArgs(string from,string to,string subject) { _from = from; _to = to; _subject = subject; } public string From { get { return _from; } } public string To { get { return _to; } } public string Subject { get { return _subject; } } } //订阅者类1 internal class Fax { public Fax(MailManager mm) { mm.NewMail += new EventHandler<NewMailEventArgs>(FaxMsg);//注册事件处理程序 //mm.NewMail += FaxMsg;//与上面等价 } public void Unregister(MailManager mm) { mm.NewMail -= new EventHandler<NewMailEventArgs>(FaxMsg);//取消事件处理程序 } private void FaxMsg(object sender, NewMailEventArgs e)//注意:处理程序的返回类型和签名必须和事件委托的返回类型和签名一致 { Console.WriteLine("Faxing mail message:"); Console.WriteLine("From:{0}, To={1}, Subject={2}",e.From,e.To,e.Subject); } } //订阅者类2 internal class Pager { public Pager(MailManager mm) { mm.NewMail +=PagerMsg;//注册事件处理程序 } public void Unregister(MailManager mm) { mm.NewMail -= PagerMsg;//取消事件处理程序 } private void PagerMsg(object sender, NewMailEventArgs e) { Console.WriteLine("Pager mail message:"); Console.WriteLine("From:{0}, To={1}, Subject={2}", e.From, e.To, e.Subject); } } }
程序输出结果如下图所示。
注意事项:1,+=和-=是事件中唯一允许使用的运算符,分别代表注册事件处理程序和取消注册事件处理程序。
2,不要误认为事件是类型,事件是类型的一种成员,所以它也不可以使用对象创建表达式(new表达式)来创建它的对象。
3,调用事件与调用委托相似(与调用方法也相似),但是要注意它的参数必须要与事件的委托匹配。
4,订阅事件(注册事件处理程序)有多种方法,可以是实例方法,静态方法,匿名方法,或lambda表达式。最常见的是使用委托形式的实例方法。如:
btn.Click+=new EventHandler(btn_Click);//等价于:btn.Click+=btn_Click;
5,EventHandler委托的第二个参数EventArgs默认是不能传递任何数据的,如果希望被设计成能传递数据,必须自定义一个从EventArgs继承的类,并使用私有字段来保存需要被传递的数据。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架