C#怎么实现委托和事件_C#如何使用delegate和event实现消息通知【详解】

梦明吖_3371

梦明吖_3371

2026-04-30

273人浏览

原创

委托和事件是运行时真实对象,非语法糖;委托本质是方法签名的类型化容器,需严格匹配参数、返回值;event仅支持+=/-=,触发须用?.invoke()并注意线程安全与内存泄漏。

c#怎么实现委托和事件_c#如何使用delegate和event实现消息通知【详解】

委托和事件不是语法糖,是运行时真实存在的对象;不理解委托的多播性和空安全调用,event 很容易在订阅者为 null 或跨线程时崩溃。

delegate 声明和实例化必须匹配签名

委托本质是“方法签名的类型化容器”,声明时就锁死了参数个数、类型、返回值。比如 public delegate void StatusChangedHandler(string status, bool isSuccess);,后续只能绑定签名完全一致的方法。

常见错误现象:

  • 编译报错 Error CS0123 No overload for 'OnLog' matches delegate 'StatusChangedHandler' —— 方法少了一个 bool 参数
  • 把 void OnLog(string s) 绑给 Func<string int></string> —— 返回值不匹配,连编译都过不去

实操建议:

frigatebird
frigatebird

使用 frigatebird npm 包在命令行与 X 交互,提供类鸟命令对等、发布/回复/文章功能以及列表自动化,且无需 X API 密钥。

下载
  • 优先用泛型内置委托:Action<t></t>、Action<t1></t1>、Func<tresult></tresult>,避免手写重复委托类型
  • 实例化时直接用方法组:StatusChangedHandler handler = LogToConsole;,不用 new StatusChangedHandler(LogToConsole)
  • 支持 lambda:handler = (s, ok) => Console.WriteLine($"{s} → {(ok ? "OK" : "FAIL")}");

event 不是字段,不能直接赋值或调用

event 是对委托字段的封装,只暴露 += 和 -= 两个操作符。它背后仍是 MulticastDelegate 实例,但外部无法绕过访问器直接读写底层委托字段。

常见错误现象:

  • myObj.StatusChanged = handler; → 编译错误:无法对事件赋值,除非在定义它的类内部
  • myObj.StatusChanged("done", true); → 编译错误:事件只能出现在 += 或 -= 左侧
  • 忘记判空直接调用:StatusChanged?.Invoke(...) 漏掉 ?,一有订阅者为 null 就抛 NullReferenceException

实操建议:

  • 触发事件必须走受保护的虚方法(如 OnStatusChanged),且始终用 ?.Invoke()
  • 不要在事件声明后直接初始化:public event Action<string> Log = s => { }; </string>—— 这会让所有实例共享同一个匿名委托,且无法取消订阅
  • 如果需要在线程安全场景下触发(如 UI 更新),先缓存委托再判空:var handler = StatusChanged; if (handler != null) handler("msg", true);

订阅/取消订阅必须成对,否则内存泄漏

事件持有对订阅方法的引用,而该方法又可能持有对所在对象的引用(尤其是实例方法)。若只订阅不取消,发布者生命周期长于订阅者时,订阅者无法被 GC 回收。

使用场景:

  • WinForms/WPF 控件事件(button.Click += OnClick;)—— 必须在 Dispose() 或 Unloaded 中 -=
  • 后台服务注册状态回调(monitor.StateChanged += OnStateChanged;)—— 服务停用时需显式取消

实操建议:

  • 用命名方法而非 lambda 订阅,否则无法取消:monitor.StateChanged += OnStateChanged; ✅,monitor.StateChanged += (s, e) => { ... }; ❌(无法 -=)
  • 在 IDisposable 实现中统一清理:StateChanged -= OnStateChanged;
  • 考虑用弱事件模式(WeakEventManager)处理 UI 场景,但仅限 WPF

跨线程触发事件要小心委托目标线程

事件本身不关心线程,但订阅者方法执行在线程上。比如从后台线程触发 ProgressChanged,而订阅者是 WinForm 的 Label.Text =,就会抛 InvalidOperationException:“线程间操作无效”。

性能 / 兼容性影响:

  • 同步触发(默认):快,但要求订阅者方法能适应当前线程上下文
  • 异步派发(如 BeginInvoke、Dispatcher.Invoke):增加调度开销,但保证 UI 安全

实操建议:

  • UI 类库应在文档里明确事件回调线程契约(例如 “所有事件都在 UI 线程触发”)
  • 后台类不主动切换线程;把线程责任交给订阅者:control.BeginInvoke((MethodInvoker)(() => label.Text = msg));
  • 避免在事件处理中做耗时操作,否则会阻塞整个委托链

委托链的多播特性是双刃剑:它让一对多通知变得简单,但也意味着任意一个订阅者抛异常都会中断后续调用;GetInvocationList() 可以拆解链手动捕获每个异常,但多数场景下,宁可让单个失败不影响整体,也别让异常静默吞掉。

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

c# gate

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
c#是什么意思
c#是什么意思

C#是一种通用的面向对象编程语言,它在.NET框架上运行,可用于开发各种类型的应用程序。本专题为大家提供c#相关的各种文章、以及下载和课程。

2023.08.08

1012

5

什么是c#
什么是c#

C#(读作C Sharp)是一种现代的、通用的、面向对象的编程语言。它由微软公司开发,于2000年首次发布,主要用于开发Windows桌面应用程序、Web应用程序、移动应用程序以及游戏开发等领域。C#是一种类型安全和托管的编程语言,它结合了C++的强大性能和C语言的简单易学特点,并引入了许多新的特性和概念,如委托、属性、泛型和异步编程等,以提高开发效率和代码可维护性。

2023.08.31

2931

3

C#中base关键字的用法
C#中base关键字的用法

在C#中,base关键字用于访问当前类的基类成员,这包括基类的字段、属性、方法、构造函数、索引器以及事件。想了解更多C#的相关内容,可以阅读本专题下面的文章。

2024.03.13

885

8

C#Task用法
C#Task用法

Task在C#中是用于表示异步操作的对象,它位于System.Threading.Tasks命名空间中。想了解更多C#中各种用法的相关内容,可以阅读本专题下面的文章。

2024.03.14

2615

11

C# 并发与异步编程
C# 并发与异步编程

本专题系统讲解 C# 异步编程与并发控制,重点介绍 async 和 await 关键字、Task 类、线程池管理、并发数据结构、死锁与线程安全问题。通过多个实战项目,帮助学习者掌握 如何在 C# 中编写高效的异步代码,提升应用的并发性能与响应速度。

2026.02.03

312

18

C# 多线程与异步编程
C# 多线程与异步编程

本专题深入讲解 C# 中多线程与异步编程的核心概念与实战技巧,包括线程池管理、Task 类的使用、async/await 异步编程模式、并发控制与线程同步、死锁与竞态条件的解决方案。通过实际项目,帮助开发者掌握 如何在 C# 中构建高并发、低延迟的异步系统,提升应用性能和响应速度。

2026.02.06

389

20

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

2026.03.11

631

24

C# Unity游戏开发与ECS架构实践
C# Unity游戏开发与ECS架构实践

本专题聚焦 C# 在 Unity 游戏开发中的应用,系统讲解 ECS(Entity-Component-System)架构设计、游戏对象管理、性能优化与内存控制策略。通过实际游戏案例,帮助开发者构建高性能、结构清晰的游戏系统,提高游戏开发效率与运行性能。

2026.04.13

329

20

c#是什么意思
c#是什么意思

C#是一种通用的面向对象编程语言,它在.NET框架上运行,可用于开发各种类型的应用程序。本专题为大家提供c#相关的各种文章、以及下载和课程。

2023.08.08

1012

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习