一、事件核心概念(必背基础)
1. 事件是什么?
事件是被 event 关键字封装的、安全的特殊委托。
事件底层完全依赖委托,但是对委托做了权限限制、安全封装。
2. 事件作用
用来监听程序发生的动作,例如:点击、移动、加载、触发、状态改变。
3. 事件设计模式:发布订阅模式
-
发布者:定义事件、在满足条件时触发事件(主动方)
-
订阅者:绑定事件处理方法,事件触发自动执行(被动方)
4. 事件本质总结
委托是用来存方法;事件是用来通知、回调、监听。
二、事件标准语法(重点)
定义事件固定语法:
访问修饰符 event 委托类型 事件名
关键字解释
-
event:将普通委托升级为事件,增加安全限制
-
EventHandler:系统自带默认事件委托(固定双参:sender、e)
-
MyClick:自定义事件名称
三、逐行代码详细解析(你提供的全部代码)
1. 定义事件代码
public static event EventHandler MyClick;
逐句解析:
-
public:公开事件,允许外部订阅
-
static:静态事件,属于类,不属于对象
-
event:声明这是一个事件,不是普通委托
-
EventHandler:使用系统默认事件委托类型
-
MyClick:自定义事件名(模拟点击事件)
EventHandler 固定方法签名规则
所有绑定该事件的方法必须满足:
void 方法名(object sender, EventArgs e)
-
sender:事件触发源(谁触发的事件)
-
e:事件参数,存储事件附带数据
2. Main 方法------订阅事件
- sender:事件触发源(谁触发的事件)
- e:事件参数,存储事件附带数据
---
2. Main 方法------订阅事件
解析:
给事件 MyClick 订阅 F1 方法
事件只能使用 +=、-=
❌ 事件禁止使用 = 赋值(普通委托可以,事件绝对不行)
3. Lambda 表达式订阅事件
MyClick += (sender, e) =>
{
Console.WriteLine("lambda表达式");
};
解析:
使用 Lambda 匿名方法快速订阅事件
自动匹配 EventHandler 的参数格式
此时事件绑定了 两个方法(多播事件)
触发事件时,两个方法从上到下依次执行
4. 触发事件代码
MyClick(null,null);
解析:
手动触发 MyClick 事件,执行所有已订阅的方法
第一个 null:sender 触发源为空
第二个 null:事件参数为空
注意:事件只能在当前类内部触发,外部无法触发
5. 事件处理方法 F1
static void F1(object sender,EventArgs s)
{
Console.WriteLine("F1方法");
}
解析:
完全符合 EventHandler 签名,是合法的事件处理方法
事件触发时自动执行该方法
四、程序完整运行流程
-
定义事件 MyClick(空事件,无订阅)
-
绑定 F1 方法到事件
-
绑定 Lambda 方法到事件
-
手动触发事件
-
依次执行 F1 → Lambda 代码
运行结果:
F1方法
lambda表达式
五、事件与委托的核心区别(必考)
1. 普通委托
-
可以用 = 赋值、+=、-=
-
任何类都可以调用、清空、修改
-
不安全
2. 事件 event
-
只能 += 订阅、-= 取消订阅
-
禁止 = 赋值(禁止覆盖清空)
-
只能在本类内部触发,外部不能触发
-
安全、适合做程序监听
一句话总结:事件 = 私有保护的委托
六、官方规范写法(优化你的代码)
你的写法:
MyClick(null,null);
企业标准安全写法(必学)
MyClick?.Invoke(null, EventArgs.Empty);
-
?. 空安全:没有订阅不会报错
-
EventArgs.Empty 官方空参数,比 null 规范
七、事件完整三步流程(背诵)
-
定义事件:public event EventHandler 事件名
-
订阅事件:事件 += 方法 / Lambda
-
触发事件:事件?.Invoke()
八、高频易错点(考试必坑)
-
❌ 事件不能写
MyClick = F1只能 += -
❌ 外部类不能触发事件,只能本类触发
-
❌ 事件不做空判断,无订阅时报错
-
❌ 事件方法参数必须是 (object, EventArgs)
-
✅ 事件本质是多播委托,可以绑定多个方法
九、终极背诵口诀
事件源自委托封,event关键字加持中
只能加减不能等,外部不能触发通
EventHandler双参数,sender源e存内容
问号调用防空错,发布订阅最正宗
------------------自定义带参数事件例子------------------------
一、案例整体介绍
本案例实现自定义委托 + 自定义带参数事件 ,是标准的 发布者-订阅者模式 实战。
功能:计算器完成加法运算后,主动触发事件,把参与计算的两个数字、计算结果推送出去,由订阅方法接收并打印。
本次不使用系统自带 EventHandler ,完全手写委托与事件,实现自定义多参数事件。
角色分工
-
发布类(Calc):定义委托、定义事件、业务逻辑执行完成后触发事件
-
订阅类(Program):绑定事件处理方法,监听事件,事件触发自动执行回调
二、发布类 Calc 逐行代码解析
1. 自定义委托(规定事件的参数格式)
//1.自定义委托:规定事件方法的格式(三个int参数、无返回值)
public delegate void AddDel(int a, int b, int sum);
解析:
委托是事件的模板,用来规定:订阅事件的方法必须是什么格式。
本委托规则:方法无返回值,必须传入 a、b、sum 三个整型参数。
2. 定义自定义事件
//2.根据自定义委托,定义事件
public event AddDel Finished;
解析:
-
event关键字:将委托封装为事件,拥有事件安全机制 -
AddDel:事件遵循的委托模板 -
Finished:事件名,含义:计算完成事件
事件本质:受保护的多播委托,只能 +=、-=,禁止直接赋值覆盖。
3. 核心业务方法 + 触发事件
public void Add(int a,int b)
{
int sum = a + b;
//3.触发事件,推送参数给所有订阅方法
Finished?.Invoke(a,b,sum);
}
逐行解析:
-
执行加法运算,得到结果 sum
-
Finished?.Invoke(a,b,sum):触发事件 -
?. 空安全判断:如果没有任何订阅方法,不会报错
-
将
a、b、sum三个参数推送订阅方法
三、订阅类 Program 逐行代码解析
1. 事件订阅绑定
Calc c = new Calc();
c.Finished += F1; //订阅事件:绑定处理方法
解析:
订阅事件固定写法:事件 += 匹配格式的方法
当 Calc 里面的 Finished 事件被触发时,自动执行 F1 方法。
❌ 事件不允许:c.Finished = F1 不能直接赋值覆盖!
2. 事件处理回调方法 F1
static void F1(int a,int b,int c)
{
Console.WriteLine($"a的值为{a},b的值为{b},c的值为{c}");
}
解析:
方法签名和自定义委托 AddDel完全一致,可以绑定事件。
作用:接收发布方推送的 a、b、sum 数据,完成打印展示。
3. 调用业务方法触发事件
c.Add(10, 20);
c.Add(30, 20);
每次调用 Add 方法 → 计算完成 → 触发 Finished 事件 → 执行 F1 打印。
四、完整执行流程(必考)
-
创建计算器对象 Calc
-
订阅 Finished 事件,绑定回调方法 F1
-
执行
Add(10,20):计算 sum=30 → 触发事件 → F1 打印 -
执行
Add(30,20):计算 sum=50 → 触发事件 → F1 打印
运行结果
a的值为10,b的值为20,c的值为30
a的值为30,b的值为20,c的值为50
五、核心知识点总结
1. 自定义事件三步固定写法(背诵)
-
定义委托:规定事件回调方法的参数、返回值格式
-
定义事件:event + 委托类型 + 事件名
-
触发事件:事件?.Invoke(参数)
2. 为什么不用 EventHandler?
系统自带 EventHandler 只能固定传 (sender,e),无法自定义多个业务参数。
需要传递自定义数据(多个参数)时,必须手写委托、手写事件。
3. 委托 VS 事件 核心区别(本题体现)
-
委托:可以 =、+=、-=,外部可以随意调用、清空
-
事件:只能 +=、-=,外部不能赋值、不能主动触发,更安全,适合业务回调
4. 空安全调用 ?.Invoke() 作用
如果没有任何方法订阅事件(事件为null),不会报错,程序稳健运行。
六、高频易错点
-
❌ 事件绑定不能用 = 只能用 +=
-
❌ 回调方法参数必须和委托完全一致,否则绑定失败
-
❌ 不写 ?.Invoke,无订阅时直接报错
-
✅ 自定义事件适合传递自定义业务数据
-
✅ 事件触发顺序:先计算、后推送、最后回调打印
七、终极背诵口诀
自定义事件三步走,先写委托后写事件
业务完成Invoke推,参数全部送外边
订阅只能加加减,禁止赋值最安全
空判断符不能省,回调自动跑满篇