C# 事件(Event)+自定义带参数事件例子

一、事件核心概念(必背基础)

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 签名,是合法的事件处理方法

事件触发时自动执行该方法


四、程序完整运行流程

  1. 定义事件 MyClick(空事件,无订阅)

  2. 绑定 F1 方法到事件

  3. 绑定 Lambda 方法到事件

  4. 手动触发事件

  5. 依次执行 F1 → Lambda 代码

运行结果:

复制代码
F1方法
lambda表达式

五、事件与委托的核心区别(必考)

1. 普通委托

  • 可以用 = 赋值、+=、-=

  • 任何类都可以调用、清空、修改

  • 不安全

2. 事件 event

  • 只能 += 订阅、-= 取消订阅

  • 禁止 = 赋值(禁止覆盖清空)

  • 只能在本类内部触发,外部不能触发

  • 安全、适合做程序监听

一句话总结:事件 = 私有保护的委托


六、官方规范写法(优化你的代码)

你的写法:

复制代码
MyClick(null,null);

企业标准安全写法(必学)

复制代码
MyClick?.Invoke(null, EventArgs.Empty);
  • ?. 空安全:没有订阅不会报错

  • EventArgs.Empty 官方空参数,比 null 规范


七、事件完整三步流程(背诵)

  1. 定义事件:public event EventHandler 事件名

  2. 订阅事件:事件 += 方法 / Lambda

  3. 触发事件:事件?.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 打印。


四、完整执行流程(必考)

  1. 创建计算器对象 Calc

  2. 订阅 Finished 事件,绑定回调方法 F1

  3. 执行 Add(10,20):计算 sum=30 → 触发事件 → F1 打印

  4. 执行 Add(30,20):计算 sum=50 → 触发事件 → F1 打印

运行结果

复制代码
a的值为10,b的值为20,c的值为30
a的值为30,b的值为20,c的值为50

五、核心知识点总结

1. 自定义事件三步固定写法(背诵)

  1. 定义委托:规定事件回调方法的参数、返回值格式

  2. 定义事件:event + 委托类型 + 事件名

  3. 触发事件:事件?.Invoke(参数)

2. 为什么不用 EventHandler?

系统自带 EventHandler 只能固定传 (sender,e),无法自定义多个业务参数

需要传递自定义数据(多个参数)时,必须手写委托、手写事件

3. 委托 VS 事件 核心区别(本题体现)

  • 委托:可以 =、+=、-=,外部可以随意调用、清空

  • 事件:只能 +=、-=,外部不能赋值、不能主动触发,更安全,适合业务回调

4. 空安全调用 ?.Invoke() 作用

如果没有任何方法订阅事件(事件为null),不会报错,程序稳健运行。


六、高频易错点

  • ❌ 事件绑定不能用 = 只能用 +=

  • ❌ 回调方法参数必须和委托完全一致,否则绑定失败

  • ❌ 不写 ?.Invoke,无订阅时直接报错

  • ✅ 自定义事件适合传递自定义业务数据

  • ✅ 事件触发顺序:先计算、后推送、最后回调打印


七、终极背诵口诀

自定义事件三步走,先写委托后写事件

业务完成Invoke推,参数全部送外边

订阅只能加加减,禁止赋值最安全

空判断符不能省,回调自动跑满篇

相关推荐
FlYFlOWERANDLEAF1 小时前
DevExpress Office File API使用记录
开发语言·c#·devoffice
程序员二叉1 小时前
【JVM】OOM详解+JVM参数+FullGC排查+CPU飙高+死锁+内存泄漏+命令大全
java·开发语言·jvm·面试
yijianace1 小时前
Python线程与多线程完全总结(从入门到理解并发本质)
开发语言·python
不知名的老吴1 小时前
线程的生命周期之线程同步
java·开发语言·jvm
richard_yuu2 小时前
C#工业上位机项目实战第九篇:可视化流程引擎完整落地,节点拖拽、连线渲染与自动化调度
c#·自动化
J2虾虾2 小时前
C 语言 void 完全用法
c语言·开发语言
会Tk矩阵群控的小木2 小时前
基于Python的iMessage短信群发与社媒多账号统一管理系统实现
开发语言·windows·python·新媒体运营·开源软件·个人开发
我是一颗柠檬2 小时前
【Java项目技术亮点】分库分表+数据路由策略:单表5000万后的架构升级方案
java·开发语言·分布式·架构
wu_ye_m2 小时前
学习c语言第35天 函数声明和定义
c语言·开发语言·学习