探索C#事件(Event)的强大应用

摘要
在现代软件开发中,对象之间的通信和交互是一个常见而重要的问题。为了解决这个问题,C#作为一种面向对象的编程语言提供了一种强大的特性:事件(Event)。事件可以帮助开发人员实现对象间的松耦合,提高代码的可读性和可维护性。本文将详细介绍C#事件的概念、使用方法以及实际应用场景,并通过丰富的示例代码帮助读者全面理解事件的魅力与威力。
目录
- 摘要
- 导言
- 一、C#事件的定义与基本语法
- 1. 什么是事件?
- 2. 事件的声明与实例化
- 3. 事件的添加与移除
- 4. 使用事件发生器引发事件
- 二、事件的订阅与处理
- 1. 使用事件处理程序(Event Handler)
- 2. 多播事件(Multicast Event)
- 3. 使用匿名方法和Lambda表达式简化事件处理过程
- 三、实践应用场景
- 1. GUI程序中的事件处理
- 2. 发布-订阅模式(Publish-Subscribe Pattern)实现消息传递
- 3. 异步编程中的事件驱动机制
- 4. 自定义事件实现对象间的通信
- 四、事件的高级应用
- 1. 事件参数(Event Arguments)与自定义事件参数类
- 2. 取消事件(Cancel Event)的处理
- 3. 事件的线程安全性与同步
- 五、事件的优势与注意事项
- 1. 优势总结
- 2. 注意事项和最佳实践
- 结论
导言
在软件开发中,我们经常会遇到需要在不同对象之间进行通信和交互的情况。传统的方法是使用回调函数或委托来实现这种通信,但这往往导致代码复杂、难以维护。幸运的是,C#中的事件机制为我们提供了一种更加灵活、高效的解决方案。
一、C#事件的定义与基本语法

1. 什么是事件?
事件是对象所触发的动作或状态变化,它将通知其他对象执行相应的操作。
2. 事件的声明与实例化
// 定义事件的委托类型
public delegate void MyEventHandler(object sender, MyEventArgs e);// 声明事件
public event MyEventHandler MyEvent;// 实例化事件委托并触发事件
MyEvent?.Invoke(this, new MyEventArgs());
3. 事件的添加与移除
// 添加事件处理程序
myObj.MyEvent += MyEventHandlerMethod;// 移除事件处理程序
myObj.MyEvent -= MyEventHandlerMethod;
4. 使用事件发生器引发事件
// 定义事件发生器的类
public class EventGenerator
{// 定义事件public event Action<string> MessageReceived;// 触发事件的方法public void OnMessageReceived(string message){MessageReceived?.Invoke(message);}
}
二、事件的订阅与处理

1. 使用事件处理程序(Event Handler)
// 定义事件处理程序
private void MyEventHandlerMethod(object sender, MyEventArgs e)
{// 处理事件逻辑
}// 订阅事件
myObj.MyEvent += MyEventHandlerMethod;
2. 多播事件(Multicast Event)
// 定义多个事件处理程序
private void EventHandler1(object sender, EventArgs e) { }
private void EventHandler2(object sender, EventArgs e) { }// 添加多个事件处理程序
myObj.MyEvent += EventHandler1;
myObj.MyEvent += EventHandler2;// 移除单个事件处理程序
myObj.MyEvent -= EventHandler1;
3. 使用匿名方法和Lambda表达式简化事件处理过程
// 使用匿名方法订阅事件
myObj.MyEvent += delegate(object sender, MyEventArgs e)
{// 处理事件逻辑
};// 使用Lambda表达式订阅事件
myObj.MyEvent += (sender, e) =>
{// 处理事件逻辑
};
三、实践应用场景

1. GUI程序中的事件处理
// 在按钮点击事件中添加处理逻辑
button.Click += (sender, e) =>
{// 处理按钮点击事件逻辑
};
2. 发布-订阅模式(Publish-Subscribe Pattern)实现消息传递
// 定义消息发布者
public class MessagePublisher
{public event Action<string> MessagePublished;public void PublishMessage(string message){MessagePublished?.Invoke(message);}
}// 订阅消息
messagePublisher.MessagePublished += (message) =>
{// 处理消息逻辑Console.WriteLine(message);
};
3. 异步编程中的事件驱动机制
// 定义异步任务
public class MyAsyncTask
{public event Action TaskCompleted;public async Task Run(){await Task.Delay(1000);TaskCompleted?.Invoke();}
}// 异步任务的事件处理方法
myAsyncTask.TaskCompleted += () =>
{// 处理异步任务完成后的逻辑
};
4. 自定义事件实现对象间的通信
// 定义事件参数类
public class MyEventArgs : EventArgs
{// 添加自定义属性public string Message { get; set; }
}// 定义事件发生器
public class EventGenerator
{public event EventHandler<MyEventArgs> MyEvent;public void TriggerEvent(string message){MyEvent?.Invoke(this, new MyEventArgs { Message = message });}
}// 订阅事件并处理
eventGenerator.MyEvent += (sender, e) =>
{Console.WriteLine(e.Message);
};
四、事件的高级应用
1. 事件参数(Event Arguments)与自定义事件参数类
在实际开发中,我们经常需要传递一些额外的信息给事件的订阅者。可以通过自定义事件参数类来实现这个目标。
// 自定义事件参数类
public class MyEventArgs : EventArgs
{public string Message { get; set; }public int Value { get; set; }
}// 定义事件发生器
public class EventGenerator
{public event EventHandler<MyEventArgs> MyEvent;public void TriggerEvent(string message, int value){MyEvent?.Invoke(this, new MyEventArgs { Message = message, Value = value });}
}
2. 取消事件(Cancel Event)的处理
在某些情况下,我们可能希望取消事件的继续执行。可以通过设置事件参数的属性来实现事件的取消。
// 自定义事件参数类
public class MyEventArgs : CancelEventArgs
{// 添加自定义属性public string Message { get; set; }
}// 定义事件发生器
public class EventGenerator
{public event EventHandler<MyEventArgs> MyEvent;public void TriggerEvent(string message){var args = new MyEventArgs { Message = message };MyEvent?.Invoke(this, args);if (args.Cancel){// 取消事件的执行}}
}
3. 事件的线程安全性与同步
在多线程环境下,使用事件可能会引发线程安全性问题。可以通过使用锁或其他同步机制来确保事件的线程安全性。
// 定义事件
public event EventHandler<MyEventArgs> MyEvent;// 引发事件的方法
private void OnMyEvent(string message)
{lock (myLockObject){MyEvent?.Invoke(this, new MyEventArgs { Message = message });}
}
五、事件的优势与注意事项
1. 优势总结
- 提高了代码的可读性和可维护性。
- 实现了对象间的松耦合,增加了代码的扩展性。
- 简化了多个对象间的通信和交互。
2. 注意事项和最佳实践
- 避免过度使用事件,以免导致事件链过长。
- 明确事件是否需要返回值,判断是否适合使用事件。
结论
C#事件是一种强大的工具,它可以极大地提高代码的可读性、可维护性和可扩展性。通过深入学习和灵活运用C#事件,我们可以更加高效地实现对象间的通信和交互。希望本文提供的知识和示例能够激发读者对C#事件的兴趣,并在实际开发中有所应用。
参考文献:
[1] Microsoft Docs, “Events (C# Programming Guide)”, https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/events/
相关文章:
探索C#事件(Event)的强大应用
摘要 在现代软件开发中,对象之间的通信和交互是一个常见而重要的问题。为了解决这个问题,C#作为一种面向对象的编程语言提供了一种强大的特性:事件(Event)。事件可以帮助开发人员实现对象间的松耦合,提高代…...
学习c#的第四天
目录 C# 变量 C# 中的变量定义与初始化 接受来自用户的值 C# 中的 Lvalues 和 Rvalues 不同类型变量进行运算 静态变量 局部变量 C# 常量 整数常量 浮点常量 字符常量 字符串常量 定义常量 扩展知识 Convert.ToDouble 与 Double.Parse 的区别 静态常量和动态常…...
解析JSON字符串:属性值为null的时候不被序列化
如果希望属性值为null及不序列化,只序列化不为null的值。 1、测试代码 配置代码: mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); 或者通过注解JsonInclude(JsonInclude.Include.NON_NULL) //常见问题2:属性为null&a…...
短视频短剧小程序系统:用技术丰富你的碎片时间
在当今快节奏的生活中,人们的休闲时间变得越来越碎片化。短视频短剧小程序系统正是利用这一现象,通过技术手段为人们提供了丰富多样的娱乐内容,让碎片时间变得更加充实。 一、短视频短剧小程序系统的技术特点 高效加载与流畅播放࿱…...
服务器数据恢复—磁盘出现坏道掉线导致raid5阵列崩溃的数据恢复案例
服务器数据恢复环境: 某品牌服务器中有一组16块SAS接口硬盘组建的raid5磁盘阵列。 服务器故障&检测: 服务器raid5阵列中有2块硬盘掉线,上层服务器应用崩溃,导致服务器数据丢失。丢失的数据主要是4个1.5TB大小的卷中的数据&am…...
Android R.fraction
来源 我是在看Android10原生代码,绘制状态栏蓝牙电量相关类中第一次看到R.fraction的,如类BatteryMeterDrawable <fraction name"battery_button_height_fraction">10%</fraction> mButtonHeightFraction context.getResources(…...
C语言精华题目锦集1
第一题 test.c文件中包括如下语句,文件中定义的四个变量中,是指针类型的是()【多选】 #define INT_PTR int* typedef int* intptr; INT_PRT a,b; int_ptr c,d;A:a B:b C:c D:d #define是宏定义,此时在程序中IN…...
头歌答案Python——JSON基础
目录 编辑 Python——JSON基础 第1关:JSON篇:JSON基础知识 任务描述 第2关:JSON篇:使用json库 任务描述 Python——XPath基础 第1关:XPath 路径表达式 任务描述 第2关:XPath 轴定位 任务描述…...
TDengine 与煤科院五大系统实现兼容性互认,助力煤矿智能化安全体系搭建
近日,涛思数据与煤炭科学技术研究院(以下简称煤科院)已完成数个产品兼容互认证工作,经双方共同严格测试,涛思数据旗下物联网、工业大数据平台 TDengine V3.X 与煤炭科学技术研究院旗下煤矿复合灾害监测监控预警系统、煤…...
231030期就业班开班咯!我在前方护航,让你稳稳入职
就业哪家强?还得看优橙! 11月9日,231030期就业班的小伙伴结束了为期8天的基础班学习,正式进入了就业班。优橙教育也为新一批就业班的同学举办了开班典礼。 典礼环节中不仅有多彩的抽奖活动,也有丰富的超值礼品,旨在鼓…...
小白学安全-漏洞编号的理解 CVE/CAN/BUGTRAQ/CNCVE/CNVD/CNNVD
1、以CVE开头,如CVE-1999-1046这样的 CVE的英文全称是“Common Vulnerabilities&Exposures”公共漏洞和暴露。CVE就好像是一个字典表,为广泛认同的信息安全漏洞或者已经暴露出来的弱点给出一个公共的名称。使用一个共同的名字,能够帮助用…...
助力燃气安全运行:智慧燃气管网背景延展
关键词:城市燃气管网、智慧燃气管网、智慧管网、智慧燃气管网解决方案、智慧燃气 01背景 当前,随着我国城市化进程不断加快,城市燃气管网也不断延伸,运行规模庞大,地下管线复杂,不少城市建设“重地上轻地…...
低代码、零代码开源与不开源:区别解析
在如今日益发展的数字时代,程序开发变得越来越重要。为了实现日益提高的业务需求,开发人员必须能够以更高效、更灵活的方式构建和交货软件解决方案。低代码和零代码开源是近几年流行的两种开发方法。本文将探讨它们与传统非开源程序开发的差别࿰…...
LabVIEW中如何在网络上使用远程VI服务器
LabVIEW中如何在网络上使用远程VI服务器 如何在网络上使用远程VI服务器? 解答: 首先,需要在远程的计算机上打开一个在VI服务器上的LabVIEW应用程序的引用。这可以通过“Open ApplicationReference“函数实现。然后用“Open VI Reference”函数打开一个…...
Centos 7rc.local脚本命令开机不执行及指定用户启动的方法
1.开机不启动 在实际生产场景中,我们喜欢在安装了一些软件服务后,将软件设置为开机自启动 配置在/etc/rc.local文件中。直接将软件服务的启动命令写在rc.local文件 注意:编辑完rc.local文件后,一定要给rc.local文件执行权限&#…...
mysql 的存储过程
一组为了完成特定功能的sql 语句的集合,写好了存储过程之后,我们可以向函数一样随时调用sql 的集合 CREATE TABLE info ( id int(3) PRIMARY KEY, name VARCHAR(15), score DECIMAL(5,2), pass varchar(12) ); 创建存储过程 创建过程 delimiter $$ #将语…...
http客户端简单demo
socket.h头文件 #pragma once #include <iostream> #include <cstring> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <string> using std::string;namespace MySocket …...
解决UniAD在高版本CUDA、pytorch下运行遇到的问题
UniADhttps://github.com/OpenDriveLab/UniAD是面向行车规划集感知(目标检测与跟踪)、建图(不是像SLAM那样对环境重建的建图,而是实时全景分割图像里的道路、隔离带等行车需关注的相关物体)、和轨迹规划和占用预测等多任务模块于一体的统一大模型。官网上的安装说明…...
ADC、DMA以及串口之间的联系和区别?
ADC、DMA和串口都是嵌入式系统中常用的模块,它们之间有以下联系和区别: 联系: ADC和DMA都是用于数据采集和传输的模块,ADC可以将模拟信号转换为数字信号,DMA可以在不经过CPU的情况下实现数据的高速传输。而串口则是一…...
jupyter lab配置列表清单
❤️觉得内容不错的话,欢迎点赞收藏加关注😊😊😊,后续会继续输入更多优质内容❤️ 👉有问题欢迎大家加关注私戳或者评论(包括但不限于NLP算法相关,linux学习相关,读研读博…...
变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析
一、变量声明设计:let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性,这种设计体现了语言的核心哲学。以下是深度解析: 1.1 设计理念剖析 安全优先原则:默认不可变强制开发者明确声明意图 let x 5; …...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...
ubuntu搭建nfs服务centos挂载访问
在Ubuntu上设置NFS服务器 在Ubuntu上,你可以使用apt包管理器来安装NFS服务器。打开终端并运行: sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享,例如/shared: sudo mkdir /shared sud…...
蓝桥杯 2024 15届国赛 A组 儿童节快乐
P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡,轻快的音乐在耳边持续回荡,小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下,六一来了。 今天是六一儿童节,小蓝老师为了让大家在节…...
【论文笔记】若干矿井粉尘检测算法概述
总的来说,传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度,通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...
Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...
QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...
selenium学习实战【Python爬虫】
selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...
Typeerror: cannot read properties of undefined (reading ‘XXX‘)
最近需要在离线机器上运行软件,所以得把软件用docker打包起来,大部分功能都没问题,出了一个奇怪的事情。同样的代码,在本机上用vscode可以运行起来,但是打包之后在docker里出现了问题。使用的是dialog组件,…...
Reasoning over Uncertain Text by Generative Large Language Models
https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...
