跳转到主内容
趣航编程网 - 趣学编程,启航技术之路!

C# 委托链实现方法 C#如何使用+=和-=操作委托

委托链本质是多播委托,通过+=/-=操作符调用Delegate.Combine/Remove实现方法追加与移除;仅void返回值委托适合链式调用,非void仅返回最后一个结果;匿名函数因实例不同导致移除失败;异常会中断后续执行,需手动遍历并捕获。 委托链本质是多播委托 在 C# 中,用
+=
给委托变量添加方法,不是简单地覆盖,而是把新方法追加到内部调用列表里——这个结构叫「多播委托」(MulticastDele gate )。只要委托类型签名一致,就能链式叠加。但要注意:
void
返回值的委托才能安全组成链;如果委托返回非
void
类型,调用链时只会拿到最后一个方法的返回值,前面的全被丢弃。 += 和 -= 实际调用 Dele gate. Combine 和 Delegate.Remove 编译器把
+=
编译成
Delegate.Combine
-=
编译成
Delegate.Remove
。这意味着:
+=
不会重复添加相同方法实例(基于引用相等判断)
-=
只移除第一个匹配的方法实例,不是全部 如果尝试移除一个从未添加过的方法,不会报错,只是静默忽略 委托链为空时,变量值为
null
,直接调用会抛
NullReferenceException
常见陷阱:匿名函数和闭包导致移除失败 下面这段代码看似能成功移除,实则无效:
Action action = () => Console.WriteLine("A"); action += () => Console.WriteLine("B"); action -= () => Console.WriteLine("B"); // ❌ 不起作用!
原因:每次写
() => ...
都创建了新的委托实例,内存地址不同。
Delegate.Remove
找不到原对象。正确做法是保留对要移除方法的引用:
Action b = () => Console.WriteLine("B"); action += b; action -= b; // ✅ 成功
调用委托链时异常会中断后续执行 委托链是顺序同步执行的。一旦某个方法抛出未捕获异常,后面的委托将完全跳过。没有内置的“继续执行下一个”的机制。若需容错,必须手动遍历
GetInvocationList()
并 try/catch 每一项:
foreach (Action a in action.GetInvocationList()) { try { a(); } catch { /* 忽略或记录 */ } }
这也意味着,别依赖委托链做关键路径的串行任务协调——它不是工作队列,也没有事务性。 委托链看起来简洁,但它的生命周期管理、异常传播、引用一致性都容易出隐性问题。真要构建事件系统或回调调度,优先考虑
event
关键字封装,或直接用
System.Collections.Generic.List
显式控制。

相关文章