欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 游戏 > C#中的事件

C#中的事件

2025/10/31 23:04:10 来源:https://blog.csdn.net/m0_61796189/article/details/143279641  浏览:    关键词:C#中的事件

事件概述

很多程序会有一个共同的需求,即当一个特定的程序事件发生时,程序的其他部分可以得到该事件已经发生的通知。事件基本上说是一个用户操作,如按键、点击、鼠标移动等等,或者是一些提示信息,如系统生成的通知。应用程序需要在事件发生时响应事件。例如,点击按钮,显示消息框。事件是一个发布-订阅模型,发布者定义了一系列程序的其他部分可能感兴趣的事件,其他类就可以注册,以便在这些事件发生时收到发布者的通知。
关于事件的重要概念:
发布器: 一个包含事件和委托定义的对象。事件和委托之间的联系也定义在这个对象中。发布器(publisher)类的对象调用这个事件,并通知其他的对象。包含事件的类用于发布事件。这被称为 发布器(publisher) 类。
订阅器: 是一个接受事件并提供事件处理程序的对象。在发布器(publisher)类中的委托调用订阅器(subscriber)类中的方法(事件处理程序)。接受该事件的类被称为 订阅器(subscriber) 类。
事件处理程序: 由订阅者注册到事件的方法,可以定义在发布者类或结构,也定义在不同的类或结构。

事件声明

发布者必须提供事件对象,事件声明的语法如下代码所示:

        public delegate void StudentHanler(object o, EventArgs e);public event StudentHanler Study;

event关键字+委托类型+事件名称
事件是成员,不是类型,因此它必须声明在类和结构中,事件成员被隐式自动初始化时为null。

订阅事件

订阅者向事件添加事件处理程序。使用+=运算符为事件添加处理程序,移除事件处理程序则使用-=,事件处理程序位于该运算符的右边。事件处理程序的规范可以是以下任意一种:

  • 实例方法的名称
  • 静态方法的名称
  • 匿名方法
  • Lambda表达式

笔者用的习惯是匿名方法和lambda表达式,如下所示

stu.Study += delegate (object o, StudyEventArgs e) { Console.WriteLine($"{e.StuName}学习中2"); };//匿名方法形式stu.Study += (o, e) =>{Console.WriteLine($"{e.StuName}学习中1");};//订阅事件 lambda表达式形式

标准事件的用法

关于事件的使用,.Net框架提供了一个标准模式,该标准模型的基础就是System名称空间声明的EventHandler委托类型,EventHandler委托类型声明如下代码所示

public delegate void EventHandler(object o,EventArgs e)
  • 第一个参数用于保存触发事件对象的引用。因为它是object类型,所有可以匹配任何类型的实例。
  • 第二个参数用来保存状态信息,指明什么类型使用于该程序,EventArgs 不能传递任何数据,它用于不需要传递数据的事件处理程序,如果想要传递数据,则需要声明一个派生于EventArgs 的类,并使用合适的字段来保存需要传递的数据。
  • 返回类型是void

通过拓展EventArgs来传递数据

为了向事件处理程序添加第二个参数来传递数据,可以需要声明一个派生EventArgs的自定义类,同时遵循标准惯例,类的名称应该以EventArgs结尾。

    public class StudyEventArgs:EventArgs//自定义类(后缀为EventArgs):基类{//用于保存数据public String stuName;public String StuName{get { return stuName; }set { stuName = value; }}//构造函数初始化public StudyEventArgs(string name){StuName = name;}

触发事件

在触发事件可以和null比较,如果事件是null,则表示没有事件处理程序,不能执行,事件触发的语法和调用方法一样:

  • 使用事件名称,后面跟着参数列表
  • 参数列表必须与事件的委托类型相匹配

常用到的触发方式有如下3种

Study?.Invoke(source, args);//触发事件 使用空运算符判断事件是否为空和使用Invoke进行触发Study事件
if(Study !=null){Study(source, args)}

另外一种是在发布者类定义一个属性,如果属性的值设置则触发,可参考应用案例
应用
笔者定义了两个类,分别为Student类和StudyEventArgs类,Student类用于声明事件,和Name属性,触发条件和事件触发(事件触发必须写在发布者类)。StudyEventArgs类用来拓展事件参数,用于传递参数
代码如下:
Student类

    public class Student{public delegate void StudentHanler(object o, StudyEventArgs e);public event StudentHanler Study;public string Name { get; set; }private bool isStart;public bool IsStart{get { return isStart; }set { isStart = value; Start(); }}public void Start(){if (IsStart){Study?.Invoke(this, new StudyEventArgs(Name));//触发事件}}

StudyEventArgs类

    public class Program{static void Main(string[] args){Student stu = new Student() { Name = "小明" };stu.Study += (o, e) =>{Console.WriteLine($"{e.StuName}学习中1");};//订阅事件 lambda表达式形式订阅stu.Study += delegate (object o, StudyEventArgs e) { Console.WriteLine($"{e.StuName}学习中2"); };//匿名方法形式订阅stu.Study += new StudentHanler(study);//委托的形式 订阅stu.IsStart = true;}static void study(object o, StudyEventArgs e) {Console.WriteLine($"{e.StuName}学习中3");}}

运行结果
在这里插入图片描述
总结:在该程序中发布者为Student类,订阅者为为Program类,使用委托形式订阅事件时study方法为事件处理程序,在=>右边。通过设置IsStart属性来控制事件的调用。其中在事件触发时Study?.Invoke(this, new StudyEventArgs(Name)),this指向该Student的实例,即对象小明

笔者不才,如以上内容理解错误,请大佬们指正!

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词