VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > 编程开发 > c#编程 >
  • 事件(Event):基于委托的通知机制

事件(Event):基于委托的通知机制

  1. 事件的核心定义
    事件是C#中实现发布-订阅模式的核心工具,它是委托的安全封装。核心特点:
    发布者(Publisher):触发事件的对象(如订单系统);
    订阅者(Subscriber):监听事件并处理的对象(如邮件服务、短信服务);
    安全限制:外部只能通过+=订阅/-=取消订阅事件,不能直vb.net教程C#教程python教程SQL教程access 2010教程接调用或赋值(避免滥用)。
    事件的本质是委托的包装器,通过event关键字声明,依赖委托定义事件的签名。
  2. 事件的基本用法
    事件的使用流程分为四步:声明委托→定义事件→订阅事件→触发事件。以下用“订单完成通知”为例说明。
    2.1 完整代码实现
    csharp
	using System;
	
	// -------------------------- 发布者:订单系统 --------------------------
	public class Order
	{
	// 1. 声明委托(或用内置委托Action<string>)
	public delegate void OrderCompletedHandler(string orderId);
	
	// 2. 定义事件(基于委托)
	public event OrderCompletedHandler OnOrderCompleted;
	
	public string OrderId { get; private set; }
	
	public Order(string orderId)
	{
	OrderId = orderId;
	}
	
	// 触发事件的方法(内部调用)
	public void CompleteOrder()
	{
	Console.WriteLine($"订单[{OrderId}]已完成");
	// 3. 触发事件:先判断是否有订阅者(避免NullReferenceException)
	OnOrderCompleted?.Invoke(OrderId);
	}
	}
	
	// -------------------------- 订阅者:邮件服务 --------------------------
	public static class EmailService
	{
	// 事件处理方法(签名与委托匹配)
	public static void SendOrderEmail(string orderId)
	{
	Console.WriteLine($"邮件服务:向用户发送订单[{orderId}]完成通知");
	}
	}
	
	// -------------------------- 订阅者:短信服务 --------------------------
	public static class SmsService
	{
	public static void SendOrderSms(string orderId)
	{
	Console.WriteLine($"短信服务:向用户发送订单[{orderId}]完成通知");
	}
	}
	
	// -------------------------- 测试代码 --------------------------
	class Program
	{
	static void Main()
	{
	// 创建发布者实例
	var order = new Order("ORD2025001");
	
	// 4. 订阅事件:将处理方法绑定到事件
	order.OnOrderCompleted += EmailService.SendOrderEmail;
	order.OnOrderCompleted += SmsService.SendOrderSms;
	
	// 触发事件
	order.CompleteOrder();
	
	// 取消订阅短信服务
	order.OnOrderCompleted -= SmsService.SendOrderSms;
	Console.WriteLine("
取消短信订阅后再次完成订单:");
	order.CompleteOrder();
	}
	}

2.2 逐行代码讲解
发布者(Order类)
委托声明:OrderCompletedHandler委托定义了事件的签名(接受string参数,无返回值);
事件定义:public event OrderCompletedHandler OnOrderCompleted:用event关键字声明事件,外部只能订阅/取消订阅;
触发事件:OnOrderCompleted?.Invoke(OrderId):?.运算符判断事件是否有订阅者,避免空引用异常;Invoke触发事件,传递订单ID。
订阅者(EmailService/SmsService)
处理方法:SendOrderEmail/SendOrderSms的签名与委托完全匹配,用于接收事件通知。
测试代码
订阅事件:order.OnOrderCompleted += EmailService.SendOrderEmail:将邮件服务的处理方法绑定到事件;
触发事件:order.CompleteOrder():内部触发事件,所有订阅者收到通知;
取消订阅:order.OnOrderCompleted -= SmsService.SendOrderSms:移除短信服务的订阅,后续事件不再通知该服务。
输出结果:
订单[ORD2025001]已完成
邮件服务:向用户发送订单[ORD2025001]完成通知
短信服务:向用户发送订单[ORD2025001]完成通知

取消短信订阅后再次完成订单: 
订单[ORD2025001]已完成 
邮件服务:向用户发送订单[ORD2025001]完成通知
  1. 系统事件示例
    事件广泛应用于.NET框架中,比如控制台的CancelKeyPress事件(处理Ctrl+C):
    csharp
	using System;
	
	class Program
	{
	static void Main()
	{
	// 订阅控制台取消事件
	Console.CancelKeyPress += (sender, e) =>
	{
	Console.WriteLine("
收到取消信号,正在清理资源...");
	e.Cancel = true; // 取消默认终止行为
	};
	
	Console.WriteLine("按Ctrl+C测试取消事件...");
	while (true) { /* 模拟程序运行 */ }
	}
	}

说明:当用户按下Ctrl+C时,触发CancelKeyPress事件,执行清理逻辑。
4. 基础知识拓展
4.1 事件vs委托:核心区别
特性 委托(Delegate) 事件(Event)
外部操作 外部可直接调用、赋值、添加/移除方法 外部仅能添加(+=)/移除(-=)方法,不能调用或赋值
安全级别 不安全(外部可随意修改委托指向) 安全(仅允许订阅/取消订阅)
使用场景 直接封装方法,用于回调或多播 发布-订阅模式,用于通知机制
本质 引用类型,直接存储方法列表 委托的封装器,编译器生成add/remove方法
4.2 事件的本质
编译器会将事件转换为私有委托字段和公共add/remove方法。例如:
csharp

	// 编译器生成的代码(简化版)
	private OrderCompletedHandler _onOrderCompleted;
	public event OrderCompletedHandler OnOrderCompleted
	{
	add { _onOrderCompleted += value; }
	remove { _onOrderCompleted -= value; }
	}

说明:外部无法直接访问_onOrderCompleted委托字段,只能通过add/remove方法操作,确保安全性。
4.3 观察者模式
事件是C#中观察者模式的实现:
观察者模式:定义对象间的一对多依赖,当一个对象状态变化时,所有依赖它的对象收到通知并自动更新;
对应关系:发布者=被观察者,订阅者=观察者,事件=通知机制。
4.4 弱事件模式
当订阅者的生命周期长于发布者时,可能导致内存泄漏(发布者持有订阅者的引用,无法被GC回收)。弱事件模式通过WeakReference避免此问题,比如.NET的WeakEventManager类。
5. 总结
事件是委托的安全封装,核心用于实现发布-订阅模式:
核心流程:声明委托→定义事件→订阅事件→触发事件;
安全特性:外部仅允许订阅/取消订阅,避免滥用;
应用场景:系统通知、UI交互、异步回调等。
掌握事件是理解C#异步编程、UI开发的关键基础。
6. 练习
实现一个温度传感器系统:
1.发布者:TemperatureSensor类,包含CurrentTemperature属性和TemperatureExceeded事件(委托Action,参数为当前温度);
2.订阅者:AlarmService类,当温度>30℃时触发报警;
3.测试:模拟温度变化,触发事件并验证报警逻辑。
参考代码框架:
csharp

	public class TemperatureSensor
	{
	public delegate void TemperatureExceededHandler(double temp);
	public event TemperatureExceededHandler TemperatureExceeded;
	
	private double _currentTemp;
	public double CurrentTemperature
	{
	get => _currentTemp;
	set
	{
	_currentTemp = value;
	if (_currentTemp >30) TemperatureExceeded?.Invoke(_currentTemp);
	}
	}
	}
	
	public static class AlarmService
	{
	public static void TriggerAlarm(double temp)
	{
	Console.WriteLine($"报警:温度超过阈值!当前温度:{temp}℃");
	}
	}
	
	// 测试
	var sensor = new TemperatureSensor();
	sensor.TemperatureExceeded += AlarmService.TriggerAlarm;
	sensor.CurrentTemperature = 32; // 触发报警

(本节完)
下一章:LINQ基础:数据查询与操作
(深入讲解LINQ的核心概念、查询语法与方法语法)

本站原创,转载请不明出处:https://www.xin3721.com/ArticlecSharp/c49375.html


相关教程