当前位置: 首页 > news >正文

C# 事件

C# 事件

1、事件的概念

1.1、事件是什么?

事件本质上来讲是一种特殊的多播委托,用于实现观察者模式,允许对象通知其他对象发生了特定动作。
事件是一种基于委托的发布订阅机制。

1.2、事件的本质

  • 事件是基于委托实现的。
  • 它提供了一种 发布-订阅(Publish–Subscribe 机制。
  • 允许一个对象在某个事情发生时 通知其他对象

简单理解:

事件 = 委托 + 发布订阅模式

2、事件的声明与使用

2.1、事件声明

2.1.1、自定义委托,进行事件声明

由于 事件本质是委托的封装 ,因此在声明事件之前必须先声明一个对应的委托类型。

  1. 定义委托类型
public delegate void PubDelegate();
  1. 声明事件
public event PubDelegate PubEvent;

2.1.2、使用内置 EventHandler 声明事件(推荐)

EventHandler 是 .NET 中最基本的事件委托,其定义如下:

public delegate void EventHandler(object sender, EventArgs e);
  • sender:触发事件的对象(通常是 this)。
  • e:事件参数,如果不需要传递额外数据,可以使用 EventArgs.Empty

代码示例:

//事件发布者
public class Button
{// 定义事件public event EventHandler Click;// 触发事件的方法public virtual void OnClick(EventArgs e){Click?.Invoke(this, e); // 安全调用,避免 NullReferenceException}
}btn.Click += OnButtonClick;// 事件处理方法
private static  void OnButtonClick(object sender, EventArgs e)
{Console.WriteLine($"事件触发者: {sender}, 参数: {e}");
}

2.1.3、使用 EventHandler<T> 传递自定义数据

如果事件需要传递额外信息,可以自定义 EventArgs 类:

public class PriceChangedEventArgs : EventArgs
{public decimal OldPrice { get; }public decimal NewPrice { get; }
}

声明事件:

public event EventHandler<PriceChangedEventArgs> PriceChanged;

触发事件:

PriceChanged?.Invoke(this, new PriceChangedEventArgs(oldPrice, newPrice));

2.1.4、自定义委托事件与EventHandler的区别

声明方式 是否需要自定义委托 特点
自定义委托事件 需要 灵活
EventHandler 不需要 .NET标准写法
EventHandler T 不需要 可传递自定义参数

image

2.2、事件使用

使用方式 作用
基类事件 子类继承并使用
接口事件 定义统一事件规范
显式接口事件 解决接口事件冲突
事件访问器 自定义注册/注销逻辑

事件不仅可以在类中使用,还可以通过 继承接口显式实现事件访问器 来扩展和控制事件的使用方式。

3、发布订阅模型的两个角色

3.1、发布者(Publisher

负责 定义和触发事件 的对象。

主要职责:

(1)、定义 事件 (2)、触发事件

代码示例:

class OrderService
{// 定义事件public event EventHandler SendCreateOrderEvent;// 触发事件public void OnSendCreateOrderEvent(){TemperatureEvent?.Invoke(this, new OrderEventArgs(order));}
}

核心职责:
决定事件什么时候发生

3.2、订阅者(Subscriber

负责 监听事件并处理事件 的对象。

主要职责:

编写 事件处理方法

将方法 订阅到事件

就是提供方法给事件进行绑定并进行处理

代码示例:

// 订阅者类 提供方法给事件
class WetSms 
{public void SendCreateOrderInfo(object sender, OrderEventArgs e){//发生短训通知给客户Console.WriteLine("微信信息:有新订单了,订单信息如下:");Console.WriteLine($"客户名称:{e.Order.Cname},小计:{e.Order.Total:C2}");}
}

核心职责:

决定事件发生后如何处理

3.3、主程序:

internal class Program{static void Main(string[] args){WetSms wetSms = new WetSms();// 将方法绑定到事件上  订阅orderService.OrderCreadedEvent += wetSms.SendCreateOrderInfo;// 调用触发事件的方法orderService.CreateOrder(order);}

3.4、事件执行的流程

完整流程如下:

  发布者 定义事件↓订阅者 订阅事件(+=)↓发布者 触发事件 Invoke↓所有订阅的方法依次执行

4、事件的特点

一个事件可以订阅多个方法

  temp.TemperatureEvent += TempLog;temp.TemperatureEvent += TempMail;temp.TemperatureEvent += TempSms;

当事件触发:顺序触发(多播委托)

  TempLog()TempMail()TempSms()

都会被调用。

5、事件与委托的异同

相同点

image

不同点

image

事件的核心总结

事件是一种基于委托的发布订阅机制:

  • 发布者 决定 定义、触发事件
  • 订阅者 决定 事件发生后如何处理
http://www.jsqmd.com/news/447356/

相关文章:

  • Grammarly自动续费踩坑?手把手教你5分钟搞定退款(附英文模板)
  • 算法市场中的模型监控:AI应用架构师的3个工具
  • 在A100-40GB环境下使用EvalScope+vLLM评测Qwen3-4B模型的完整实践指南
  • LangFlow实战:5分钟用FastAPI+React搭建你的第一个AI工作流(附避坑指南)
  • 基于nodejs的污泥图像库图片发布分享系统的设计与实现
  • 从enum到enum class:手把手教你改造遗留C++代码(含性能对比测试)
  • 5分钟搞定!Docker+Ubuntu 22.10快速搭建内网DNS服务器(附端口冲突解决方案)
  • ADS实战:5分钟搞定多频段阻抗匹配(附Smith圆图技巧)
  • 4K/8K视频开发者必看:如何正确计算不同分辨率下的HDMI带宽需求
  • 从振动数据到动画展示:手把手教你用ODS分析机械结构变形
  • Workqueue调试指南:如何用ftrace揪出CPU占用100%的kworker
  • CISCO策略路由避坑指南:当route-map遇到ACL时的6种行为模式全解析
  • Unity Addressable资源管理进阶:如何高效利用标签和预加载优化性能
  • Dyna-Q算法实战:用Python模拟悬崖漫步环境(附完整代码)
  • 线性代数实战:如何用Python快速验证矩阵迹与特征值的关系
  • 提示工程架构师指南:用Agentic AI实现公交智能排班系统
  • VS2019项目重命名全攻略:从解决方案到命名空间一键搞定
  • 实用指南:使用Scikit-learn构建你的第一个机器学习模型
  • Ubuntu22.04上iRedMail邮件服务器搭建全攻略:从下载到配置的避坑指南
  • Scrutor隐藏技巧:用装饰器模式给.NET Core服务加日志竟如此简单
  • 初中物理必看:用几何相似三角形轻松搞定凸透镜成像公式推导
  • Simscape模型共享避坑手册:如何打包你的仿真文件才不会让队友踩到路径雷?
  • MySQL聚合函数避坑指南:为什么你的SUM()结果总是不对?
  • Docker离线部署OpenWebUI全流程指南:从镜像迁移到数据卷备份
  • MATLAB新手必看:5分钟搞定Simulink Buck变换器开环仿真(附参数设置截图)
  • 别再复制粘贴了!用OpenSSL生成自签名证书的5个专业技巧(2023最新版)
  • 完整教程:(77页PPT)健康医疗大数据整体规划方案(附下载方式)
  • 用MATLAB玩转语音变声:从频谱分析到GUI界面设计的完整实战指南(附源码)
  • WPF Frame控件实战:5分钟搞定页面跳转与传参(附完整代码示例)
  • 科技写作避坑指南:从选题到发表的完整流程解析