多播委托

news/2024/12/28 15:43:30/文章来源:https://www.cnblogs.com/one966/p/18637558

 

引言

在 C# 中,委托(Delegate)是一种类型安全的函数指针,允许将方法作为参数传递。多播委托(Multicast Delegate)则是可以调用多个方法的委托实例。本文将详细介绍多播委托的概念、使用场景以及如何在实际开发中应用多播委托。

什么是委托?

委托的基本概念

委托是 C# 中的一种类型,它封装了对具有特定参数列表和返回类型的静态或实例方法的引用。通过委托,你可以将方法作为参数传递给其他方法,从而实现回调机制。

// 定义一个委托类型
public delegate void MyDelegate(string message);// 定义两个符合委托签名的方法
public void Method1(string message)
{Console.WriteLine("Method1: " + message);
}public void Method2(string message)
{Console.WriteLine("Method2: " + message);
}

 

创建和使用委托实例

public class Program
{public static void Main(){// 创建委托实例并绑定方法MyDelegate del = new MyDelegate(Method1);// 调用委托del("Hello, World!");}
}

  

什么是多播委托?

多播委托的概念

多播委托是指可以调用多个方法的委托实例。当调用多播委托时,它会依次调用所有绑定的方法。C# 中的所有委托都是多播委托,即使它们只绑定了一个方法。

创建多播委托

可以通过 + 操作符将多个方法绑定到同一个委托实例上,形成多播委托。

public class Program
{public static void Main(){// 创建委托实例并绑定第一个方法MyDelegate del = new MyDelegate(Method1);// 使用 + 操作符添加第二个方法del += new MyDelegate(Method2);// 调用多播委托del("Hello, World!");}
}

输出结果

Method1: Hello, World!
Method2: Hello, World!

  

 

多播委托的特性

方法调用顺序

多播委托中的方法按它们被添加的顺序依次调用。如果需要改变调用顺序,可以通过重新组合委托实例来实现。

public class Program
{public static void Main(){MyDelegate del1 = new MyDelegate(Method1);MyDelegate del2 = new MyDelegate(Method2);// 组合委托实例MyDelegate combinedDel = del2 + del1;// 调用组合后的委托combinedDel("Hello, World!");}
}

移除方法

可以通过 - 操作符从多播委托中移除某个方法。

public class Program
{public static void Main(){MyDelegate del = new MyDelegate(Method1) + new MyDelegate(Method2);// 移除 Method1del -= new MyDelegate(Method1);// 调用委托del("Hello, World!");}
}

 

空委托检查

在调用多播委托之前,最好检查其是否为 null,以避免空引用异常。

public class Program
{public static void Main(){MyDelegate del = null;// 检查委托是否为 nullif (del != null){del("Hello, World!");}else{Console.WriteLine("No methods to invoke.");}}
}

多播委托的应用场景

事件处理

多播委托最常见的应用场景之一是事件处理。C# 的事件机制基于多播委托,允许多个订阅者响应同一事件。

using System;public class Publisher
{// 定义事件public event EventHandler<MyEventArgs> MyEvent;// 触发事件的方法public void TriggerEvent(){OnMyEvent(new MyEventArgs { Message = "Event Triggered" });}// 保护方法用于触发事件protected virtual void OnMyEvent(MyEventArgs e){MyEvent?.Invoke(this, e);}
}public class Subscriber
{public void HandleEvent(object sender, MyEventArgs e){Console.WriteLine($"Subscriber received: {e.Message}");}
}public class MyEventArgs : EventArgs
{public string Message { get; set; }
}public class Program
{public static void Main(){var publisher = new Publisher();var subscriber1 = new Subscriber();var subscriber2 = new Subscriber();// 订阅事件publisher.MyEvent += subscriber1.HandleEvent;publisher.MyEvent += subscriber2.HandleEvent;// 触发事件publisher.TriggerEvent();}
}

  

 

日志记录

多播委托也可以用于日志记录系统,允许多个日志记录器同时处理日志消息。

public delegate void Logger(string message);public class FileLogger
{public void LogToFile(string message){Console.WriteLine($"Logged to file: {message}");}
}public class ConsoleLogger
{public void LogToConsole(string message){Console.WriteLine($"Logged to console: {message}");}
}public class Program
{public static void Main(){Logger logger = new Logger(new FileLogger().LogToFile);logger += new Logger(new ConsoleLogger().LogToConsole);logger("This is a log message.");}
}

  

所有委托都是 MulticastDelegate 吗?

在 C# 中,所有委托类型实际上都继承自 MulticastDelegate 。这意味着从技术上讲,所有的委托实例都可以被视为多播委托(Multicast Delegate),即使它们只绑定了一个方法。然而,这并不意味着每个委托实例都会实际绑定多个方法。

1. 委托的底层实现

C# 的委托是基于 System.MulticastDelegate 类实现的。MulticastDelegate 继承自 System.Delegate,并添加了对多播支持的功能。因此,任何通过 delegate 关键字定义的委托类型,其实例都可以包含多个方法调用列表(即调用链)。

public delegate void MyDelegate(string message);

  

上述代码定义了一个名为 MyDelegate 的委托类型,它实际上继承自 MulticastDelegate

2. 单播委托 vs 多播委托

  • 单播委托:当一个委托实例只绑定一个方法时,我们通常称之为单播委托。虽然它是 MulticastDelegate 的实例,但它的调用链中只有一个方法。
MyDelegate del = new MyDelegate(Method1);
  • 多播委托:当一个委托实例绑定多个方法时,我们称之为多播委托。这些方法会按顺序依次调用。
MyDelegate del = new MyDelegate(Method1) + new MyDelegate(Method2);

3. 为什么说所有委托都是 MulticastDelegate

从类层次结构的角度来看,所有委托类型都继承自 MulticastDelegate,因此它们具备多播的能力。但这并不意味着每个委托实例都会实际使用这一能力。你可以选择性地将多个方法绑定到一个委托实例上,也可以只绑定一个方法。

4. 验证委托类型

你可以通过反射来验证这一点:

using System;public class Program
{public static void Main(){// 定义一个委托类型public delegate void MyDelegate(string message);// 创建委托实例MyDelegate del = new MyDelegate(Method1);// 检查委托类型Console.WriteLine(del.GetType().BaseType);  // 输出: System.MulticastDelegate}public static void Method1(string message){Console.WriteLine("Method1: " + message);}
}

  

输出结果:

System.MulticastDelegate

  

5. 总结

  • 所有委托类型都继承自 MulticastDelegate,因此理论上所有委托实例都可以作为多播委托使用。
  • 实际使用中,委托实例可以是单播或多播,取决于你是否将多个方法绑定到同一个委托实例上。
  • 灵活性:这种设计提供了极大的灵活性,允许你在需要时轻松扩展委托的功能,而无需改变委托类型的定义。

总结

多播委托是 C# 中一种强大的功能,允许你将多个方法绑定到同一个委托实例上,并按顺序调用这些方法。它们广泛应用于事件处理、日志记录等场景,简化了代码逻辑并提高了灵活性。通过本文的介绍,希望你能更好地理解和应用多播委托,提升你的 C# 编程技能。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/860416.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

『联合省选2025集训』『图的连通性进阶』 知识点 总结

若有长风绕旗,那便是我在想你了。前言若有长风绕旗,那便是我在想你了。这周讲了个图论连通性板块的一些进阶知识,周六全国第一给我们讲了一些树上的问题,感觉树剖板块实现难度较大,后面几道偏思维的题会有些许好转。 这里就先写写连通性相关的进阶的一些知识点吧。 主要涵…

『联合省选2025集训』『耳分解,双极定向,三连通分量』 知识点 总结

若有长风绕旗,那便是我在想你了。前言若有长风绕旗,那便是我在想你了。这周讲了个图论连通性板块的一些进阶知识,周六全国第一给我们讲了一些树上的问题,感觉树剖板块实现难度较大,后面几道偏思维的题会有些许好转。 这里就先写写连通性相关的进阶的一些知识点吧。 主要涵…

第七-八次作业总结

一、前言 该系列题目均为设计与实现一个家居强电电路模拟程序,题目难度复杂度逐步提升,题目数量和输入信息也逐步增加。以下是对这两道题的总结: 1. 知识点家居强电电路模拟程序-3 受控窗帘设备的模拟 多个并联电路串联在一起的情况 串联电路中包含其他串联电路的情况 家居强…

AD 原理图如何进行DRC检查

如果画到PCB才发现原理图画错了,那么就为时太晚了。 画完或者后期修改PCB应该及时进行原理图的DRC检查。 1. 右下角Panels打开工程: 2. 然后我们选中整个工程的工程处,点击右键: 3. 然后左键点击compile PCB Project......... : 参考资料: https://www.fanyedu.com/content…

Vue3甘特图 - dhtmlx-gantt

Vue3甘特图 <template><div style="height:100%; background-color: white"><div id="gantt_here" style="width:100%; height:100%;"></div></div> </template><script setup> import { onMounted }…

恍恍惚惚,走到了尾声

课程链接 https://edu.cnblogs.com/campus/fzu/SE2024/作业链接 https://edu.cnblogs.com/campus/fzu/SE2024/homework/13315作业目标 回顾自己的软工实践课程学号 102202157一、学期回顾 1.1 回顾你对于软件工程课程的想象在课程开始前,我一直以为软件工程课程会聚焦于各种编…

转正了!!!!!!!!

近期&感受、问题: 1.版本优化描述:秘境排行榜;一键探险功能的顺序;背包随机类宝箱一键开启;美食家一键合成闪光美食;电玩活动跳过动画功能;许愿池自动投币;结晶一键熔炼 感受/反思:感觉自己菜菜的QAQ,各种版本的本地数据处理错误(删早了删晚了/先notify后notify…

Navicat密码导出解密导入到DataGrip中

使用Navicat导出密码:目前使用Navicat17亲测有效使用php解密代码 <?php class NavicatPassword {protected $version = 0;protected $aesKey = libcckeylibcckey;protected $aesIv = libcciv libcciv ;protected $blowString = 3DC5CA39;protected $blowKey = null;protec…

鸿蒙原生页面高性能解决方案上线OpenHarmony社区 助力打造高性能原生应用

随着HarmonyOS NEXT的正式推出,鸿蒙原生应用开发热度高涨,数量激增。但在三方应用鸿蒙化进程中,性能问题频出。为此,HarmonyOS NEXT推出了一整套原生页面高性能解决方案,包括Nodepool、HMrouter和DataCache 三大解决方案,并上架OpenHarmony开源社区,分别针对应用页面滑动…

数值计算方法(2) 数值积分方法

+++ date = 2024-12-21T13:49:00+08:00 draft = true title = 数值计算方法(2) 数值积分方法 +++ 初次发布于我的个人文档 上一期讲了插值方法,这一次自然是要运用一下插值方法了。所以这一期的主题是用插值方法计算定积分。 机械求积方法 下面我们来介绍一下怎么用插值法来得…

AI烟雾监测识别摄像机

AI烟雾监测识别摄像机的应用范围广泛,不仅可以安装在家庭、商业建筑、工厂等场所,还可以应用于地铁、火车站等公共场所,为人们的生命财产安全提供全方位的保障。总的来说,AI烟雾监测识别摄像机作为智能化安全防范的重要工具,具有广阔的应用前景和社会意义。通过提高火灾预…

Omnissa Horizon Clients 2412 发布 - 虚拟桌面基础架构 (VDI) 和应用软件

Omnissa Horizon Clients 2412 发布 - 虚拟桌面基础架构 (VDI) 和应用软件Omnissa Horizon Clients 2412 发布 - 虚拟桌面基础架构 (VDI) 和应用软件 Omnissa Horizon,之前称为 VMware Horizon, 通过高效、安全的虚拟桌面交付增强您的工作空间 请访问原文链接:https://sysin.…