多播委托是严格维护的调用链,仅+=安全追加,=会切断链;调用前必须判空(?.Invoke()),-=要求方法指针完全一致,异常会中断整个链,需手动遍历并捕获各委托异常。

多播委托不是“自动支持多个方法”的魔法容器,它是一条严格维护的调用链——用错赋值、移除或异常处理方式,链就断了,甚至悄无声息地漏掉订阅者。
+= 是唯一安全的追加方式,= 会直接切断整条链
多播委托的“多播”能力完全依赖 += 运算符背后的 Delegate.Combine 逻辑。直接用 = 赋值,等同于抛弃原有委托实例,新建一个单方法委托。
- 错误写法:
handler = MethodA; handler = MethodB;→ 最终只执行MethodB - 正确写法:
handler += MethodA; handler += MethodB;→ 按序执行两者 -
+=对null左操作数安全:即使handler初始为null,第一次+=也会自动初始化,无需提前new Action()
调用前必须用 ?.Invoke(),不能靠“刚加过就肯定不为空”赌运气
委托变量随时可能被 -= 清空,或从未被赋值。不判空直接调用 handler(),运行时必抛 NullReferenceException。
通过Gate-Info和Gate-News MCP进行宏观驱动的加密货币分析,用于CPI、NFP、美联储、利率、工资等宏观因素与加密货币、日历或指标的关联。
- 安全写法:
handler?.Invoke();(推荐)或if (handler != null) handler(); - 不推荐把
?.Invoke()包在try/catch里——空引用是可预防的逻辑缺陷,不是预期异常分支 - 若委托返回值(如
Func<int>),?.Invoke()会返回default(int)(即0),需确认这是否符合业务语义
-= 移除失败?大概率是方法引用不一致
-= 不是按签名匹配,而是按方法指针(含闭包捕获状态)严格相等。匿名函数每次定义都生成新实例,无法移除。
- 命名方法安全:
handler += ProcessLog; handler -= ProcessLog; - Lambda 必须复用变量:
var logAction = () => Console.WriteLine("log"); handler += logAction; handler -= logAction; - 以下写法无效:
handler += () => Console.WriteLine("x"); handler -= () => Console.WriteLine("x");—— 两个 lambda 是不同对象 - 循环中动态创建委托再
-=,极易因引用不一致导致内存泄漏或重复触发
一个方法抛异常,后续所有方法都不执行
这是多播委托最常被忽略的行为:调用链是同步、线性的,没有内置容错机制。异常不会被吞掉,也不会跳过,而是立即终止整个链。
- 典型现象:
handler += A; handler += B; handler += C;,若B抛异常,则C永远不会被调用 - 如需“尽力执行”,必须手动遍历:
foreach (var d in handler?.GetInvocationList() ?? Array.Empty<Delegate>()) { try { d.DynamicInvoke(); } catch { /* 记录但不中断 */ } } - 不要试图用
try/catch包裹handler?.Invoke()来“兜底”——那只能捕获第一个方法的异常,后面的方法根本没机会运行
真正难的不是写对 += 和 -=,而是意识到多播委托本质是裸链表:没有重试、没有异步调度、没有异常隔离。所有健壮性都得靠你自己一层层补上。

















