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推,参数全部送外边

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

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

相关推荐
hez20101 天前
在 .NET 上构建超大托管数组
c#·.net·.net core·gc·clr
雨落倾城夏未凉7 天前
第四章c#方法-参数数组和可选参数(16)
后端·c#
唐青枫8 天前
线程不是越多越快:C#.NET Thread 生命周期、同步与后台工作线程实战
c#·.net
唐青枫9 天前
别只会反射:C#.NET Emit 动态生成代码实战详解
c#·.net
咕白m6259 天前
.NET 环境下 Word 超链接批量提取方案
c#·.net
用户91721561902119 天前
C# 通信协议增量解析:用状态机处理半包和粘包
c#
小码编匠10 天前
C# 工控上位机必备:数据转换工具类与十个核心模块
后端·c#·.net
唐青枫12 天前
别再乱用 StartNew:C#.NET TaskFactory 任务调度实战详解
c#·.net
Artech12 天前
[MAF预定义的AIContextProvider-03]ChatHistoryMemoryProvider——赋予Agent从经验中学习的能力
ai·c#·agent·memory·maf
Scout-leaf14 天前
C#摸鱼实录——IoC与DI案例详解
c#