当前位置: 首页 > news >正文

深入理解C#委托操作:添加、移除与调用全解析

关键词:委托不可变性 · 多播委托 · 调用列表管理

⚙️ 一、委托的核心特性:不可变性

看似“添加”,实为新建

使用 += 为委托“添加”方法时(如 delVar += SCl.m3;):

  • 系统创建全新委托对象
  • 新委托的调用列表 = 原列表 + 新增方法
  • 原委托对象保持不变(内存地址不变)

✅ 本质:通过新建实现“修改”,符合委托不可变原则

内存变化图解

MyDel delVar = inst.MyM1;  // 初始委托 (指向方法1)
delVar += SCl.m3;          // 新建委托 (方法1+方法2)
delVar += X.Act;           // 再新建委托 (方法1+2+3)

🧩 二、安全移除方法的机制

-= 运算符的运作逻辑

delVar -= SCl.m3;  // 从调用列表移除方法
  • 创建新委托对象,复制除目标方法外的所有引用
  • 移除规则:
    • 从列表尾部向前搜索
    • 仅移除第一个匹配的方法实例
    • 试图移除不存在的方法时静默忽略

空委托防护

// 正确检查方式
if (delVar != null) 
{delVar(55); 
}
// 或使用空条件运算符 
delVar?.Invoke(65);

⚠️ 未检查空委托直接调用将抛出 NullReferenceException

📡 三、委托调用的双模式与陷阱

image

关键特性:

  • 参数传递:调用时传入的参数应用于所有方法
  • 重复执行:若同一方法在列表中出现多次,每次都会被调用
  • 输出参数:需特殊处理(避免值覆盖问题)

💻 四、完整实例解析

delegate void PrintFunction();  // 无返回值委托 class Test
{public void Print1() => Console.WriteLine("Print1 -- instance");public static void Print2() => Console.WriteLine("Print2 -- static");
}class Program
{static void Main(){var t = new Test();PrintFunction pf = t.Print1;  // 初始化// 添加三个方法(实际新建两次委托)pf += Test.Print2;  pf += t.Print1;     pf += Test.Print2;pf?.Invoke();  // 安全调用 }
}

输出结果:

Print1 – instance
Print2 – static
Print1 – instance
Print2 – static

🔑 关键点总结

  • 不可变性是核心:所有“修改”操作实质是创建新委托对象
  • 移除顺序敏感:从列表尾部开始匹配移除首个目标方法
  • 空委托防护:必须使用 if (delVar != null) 或 ?. 运算符
  • 调用成本:每次调用遍历整个调用列表,需注意性能影响

掌握委托的不可变本质,能有效避免异步编程中的常见陷阱。建议在事件处理等场景中始终遵循「添加后必移除」原则,防止内存泄漏问题。

http://www.lqws.cn/news/558415.html

相关文章:

  • 港澳地区,海外服务器ping通可能是地区运营商问题
  • MySQL为什么要使用b+树
  • 1 Studying《Computer Architecture A Quantitative Approach》1-4
  • 鸿蒙HarmonyOS 5小游戏实践:数字记忆挑战(附:源代码)
  • 信号处理学习——文献精读与code复现之TFN——嵌入时频变换的可解释神经网络(下)
  • 给定一个整型矩阵map,求最大的矩形区域为1的数量
  • Insar 相位展开真实的数据集的生成与下载(随机矩阵放大,zernike 仿真包裹相位)
  • Launcher3中的CellLayout 和ShortcutAndWidgetContainer 的联系和各自职责
  • 剑指offer50_0到n-1中缺失的数字
  • python -日期与天数的转换
  • autoas/as 工程的RTE静态消息总线实现与端口数据交换机制详解
  • 解决flash-attn安装报错的问题
  • 【C】陷波滤波器
  • 鸿蒙开发:资讯项目实战之底部导航封装
  • MySQL之MVCC实现原理深度解析
  • 类和对象(中)
  • springboot+Vue驾校管理系统
  • 开疆智能ModbusTCP转CClinkIE网关连接台达DVP-ES3 PLC配置案例
  • Java-正则表达式
  • 测量 Linux 中进程上下文切换需要的时间
  • cocos creator 3.8 - 精品源码 - 挪车超人(挪车消消乐)
  • 同步日志系统深度解析【链式调用】【宏定义】【固定缓冲区】【线程局部存储】【RAII】
  • 蚂蚁百宝箱体验:如何快速创建“旅游小助手”AI智能体
  • LINUX628 NFS 多web;主从dns;ntp;samba
  • AlphaGenome:基因组学领域的人工智能革命
  • Linux离线搭建Redis (centos7)详细操作步骤
  • 深入解析 Electron 核心模块:构建跨平台桌面应用的关键
  • 《Go语言高级编程》玩转RPC
  • Vue.js 中的 v-model 和 :value:理解父子组件的数据绑定
  • 网络 : 传输层【UDP协议】