首页 > 编程语言 >C# - 多播委托 125

C# - 多播委托 125

时间:2023-08-31 10:44:06浏览次数:46  
标签:多播 Console 委托 md C# 125 方法 public

C# - 多播委托 125

首发2023-08-07 05:23·源丁编程

#头条创作挑战赛#

C#多播委托(委托链)是一种特殊的委托类型,特殊在可以将多个相同签名的方法绑定到同一个委托实例上,调用委托实例时会一次性触发所有绑定的方法

多播委托使用特殊的加法和减法运算符来进行方法绑定和解绑操作;使用加法运算符(+=)将一个方法绑定到委托实例上,使用减法运算符(-=)将一个方法从委托实例上解绑;当调用委托实例时,所有绑定的方法都将被调用

using System;

namespace _5多播委托
{
    //实例类
    public class MyClass
    {
        //相同签名的实例方法
        public void M1()
        {
            Console.WriteLine("M1");
        }
        public void M2()
        {
            Console.WriteLine("M2");
        }
        public void M3()
        {
            Console.WriteLine("M3");
        }
        public void M4()
        {
            Console.WriteLine("M4");
        }
        public void M5()
        {
            Console.WriteLine("M5");
        }
    }
    //定义无返回值委托
    public delegate void MyDelegate();
    public class Program
    {
        public static void Main(string[] args)
        {
            MyClass mc = new MyClass();
            //为委托赋值实例方法
            MyDelegate md = mc.M1;
            //使用+=将其他方法添加进md的委托组中
            md += mc.M2;
            md += mc.M3;
            md += mc.M4;
            md += mc.M5;
            //调用委托实例,使用方法都会执行
            md();
            Console.WriteLine("========================");
            //使用-=将M4从委托组中移除
            md -= mc.M4;
            //再次调用委托实例时只会执行
           //除 M4以外的其他方法
            md();
            Console.ReadKey();
        }
    }
}

 

使用多播委托的注意事项:

1)调用委托时执行方法顺序与添加方法时的顺序一样,但是不能依赖与此顺序(主要是其底层机制并没有保证一定都是这个顺序,如果其底层机制发生改变,就会变成潜在的bug)

2)如果添加多个方法时使用的是 = 而不是 += ,就会覆盖掉之前添加的方法,只执行从 = 开始之后的所有+=方法,如之后还有 = 就会覆盖之前所有 =与+= 的方法,之后的不受影响

总之一句话,只要多播委托中出现等号,就会覆盖之前所有的=,+=与-=方法

MyDelegate md = mc.M1;
//使用+=将其他方法添加进md的委托组中
md += mc.M2;
//如果最后一个还是+=
//即md =+ mc.M5;
//就会执行M3-M5方法
//M1,M2方法会被 M3覆盖掉
md = mc.M3;
md += mc.M4;
//会覆盖掉之前所有的方法
//只执行M5
md = mc.M5;
//如果M5后面只有+=,如+=M6;+=M7;
//其执行结果为 M5-M7方法输出结果

//调用委托实例,使用方法都会执行
md();
//类似一个变量被多次赋值
//变量值保存最后一次的赋值结果

示例中,只会执行最后一次=号的方法

3)如果多播委托都有返回值,只会返回委托中最后添加方法的返回值,如果想要多播委托中每个方法的返回值,需要通过循环遍历,调用委托中的每个方法,实现获取每个方法的返回值

通过委托实例的调用GetInvocationList()方法,返回当前委托中的所有的方法,返回值类型是一个Delegate数组(委托数组)

通过反编译工具查看:所有的委托都继承自抽象类MulticastDelegate,而MulticastDelegate又继承自Delegate类(abstract也是抽象类)

多播委托内部就是将绑定在当前委托对象上的每个方法,又转换为一个委托对象,并且存储在了一个叫_invocationList的object 数组中,当调用委托时,其实就是循环遍历_invocationList数组,并且调用其中的每一个委托

 //定义有返回值委托 
public delegate int YouDelegate();
 public class YouClass
 {
     public int M1()
     {
         return 1;
     }
     public int M2()
     {
         return 2;
     }
     public int M3()
     {
         return 3;
     }
 }
 public class Program
 {
     public static void Main(string[] args)
     {
         YouClass yc=new YouClass();
         YouDelegate yd1 = yc.M1;
         yd1 += yc.M2;
         yd1 += yc.M3;
         //接收多播委托的返回值
         int num1 = yd1();//3
         Console.WriteLine("yd1={0}",num1);
         Console.WriteLine("================");
         YouDelegate yd2 = yc.M3;
         yd2 += yc.M2;
         yd2 += yc.M1;
         //接收多播委托的返回值
         int num2 = yd2();//1
         Console.WriteLine("yd2={0}", num2);  
        Console.WriteLine("=====================");
        YouDelegate yd3 = yc.M1;
        yd3 += yc.M2;
        yd3 += yc.M3;
        //通过委托的GetInvocationList()方法得到委托数组
        Delegate[] dgs = yd3.GetInvocationList();
        foreach (var dgitem in dgs)
        {
            //将当前对象dgitem强制转换为
            //自定义的委托类型YouDelegate
            YouDelegate ydItem = (YouDelegate)dgitem;
            //调用Invoke()方法,执行当前委托中的方法
            int x = ydItem.Invoke();
            Console.WriteLine("x={0}",x);
        }
         Console.ReadKey();
     }
}

多播委托返回值

4)多播委托中的异常委托,从方法的异常地方往后以及之后的方法不再执行

public int M2()
{
    throw new Exception("抛异常了,之后不再执行");
    return 2;
}

委托链中方法抛异常

5)委托的不可变性,与字符串的特性类似,主要表现在内存方面(了解即可)

昨天#山东##德州#突发#地震#,看#今日头条##短视频#有许多人发布收到#地震预警#信息的视频,通过预警信息得以提前撤离至安全地带,愿所有人平安无事,感谢国家地震预警系统的提醒减少人员伤亡事件

标签:多播,Console,委托,md,C#,125,方法,public
From: https://www.cnblogs.com/sexintercourse/p/17668964.html

相关文章

  • C#半自动操作微信
    引言上个月,在一个群里摸鱼划水空度日,看到了一个老哥分享的一个微信自动化的一个类库,便下载了他的Demo,其本意就是模拟鼠标来操作UI,实现UI自动化;然后自己在瞎琢磨研究,写了一个简单的例子,用来获取好友列表,获取聊天列表,以及最后一次接收或者发送消息的时间,以及最后一次聊天......
  • IDEA cant resolve symbol String
    问题:在做新项目时报IDEAcantresolvesymbolString(IDEA不能识别String类型)      一脸懵,不光这个这样,其他的第三方的包也没法导进来猜测:刚开始以为是maven依赖没用导进来,后来发现String类竟然也不行,     于是猜测是JDK的问题,重新设置了一下JDK,发现也不......
  • C++读取调用接口返回的json数据
    1、引入头文件#include<boost/property_tree/ptree.hpp>#include<boost/property_tree/json_parser.hpp>ViewCode2、读取json数据方法,http请求中的chunked传输数据会返回数据的长度,在最后一个chunked中其头部长度定为0//读取json文件{"name":"zhangsan","age":25}......
  • IPAddress 类、IPInterfaceProperties 类、IPGlobalProperties 类
    一、IPAddress类IPAddress类在System.NET命名空间中,它只能单纯地用来保存一般地址信息。System.Net.NetworkInformation命名空间中还有几种IP地址有关的类,用来保存特定类型地址的相关信息,如:相关类:IPAddressCollection保存一组IPAddres......
  • 一些 trick
    图论有关于树/DAG的构造等,可以考虑从叶子/入读为零的节点开始删点。树据结构有关于维护下标大小信息的合并,可以借助线段树上本身的左儿子下标小于有儿子下标简单处理。维护一个三元组\((a,b,c)\)的信息,看看是否能拆成\((a,b)+c\)的形式更易维护。树剖的边转点:钦定边......
  • unistr函数将数据库表中的unicode转为字符(\u2161转为罗马数字Ⅱ)
    一、背景在前端页面用户输入罗马数字Ⅱ时,数据存到数据库会转为Unicode编码\u2161,需通过函数重新将Unicode编码转换回去。二、uninstr函数unistr(\xxxx)将Unicode编码转换回原来的形式,因为Unicode是带有u的,即\uxxxx,需要将u给去掉,变成oracle可识别的格式,否则oracle会提示错误。......
  • centos 安装 docker-compose 的快速简单办法
    直接使用yuminstalldocker-compose 会返回nothingtodo,可以使用pip3来安装安装DockerCompose(1)执行如下命令安装 pip3:yum-yinstallpython3-pippip3install--upgradepip-ihttps://pypi.tuna.tsinghua.edu.cn/simple (2)执行如下命令安装 docker-compose:......
  • covers和contains的区别?
    covers:b上的每个点都在a上(边界和内部),且所有点都不在a外部。属于相交的一种。对应九交模型参数为:T*****FF*\*T****FF*\***T**FF*\****T*FF*注意和contains的区别。参考:https://blog.csdn.net/whl0071/article/details/127127256 参考2:https://www.cnblogs.com/oloroso/p/1429......
  • C# 中的锁对象SpinLock,Mutex,ReaderWriteLockSlim,SemaphoreSlim
    在C#中,有多种锁类型可用于控制并发访问和保护共享资源。以下是其中一些锁类型及其简要介绍:SpinLock:SpinLock是一种自旋锁,它在使用时会忙等待直到获取到锁为止,因此适用于低延迟应用程序。由于自旋操作可能会消耗CPU资源,因此SpinLock最适合在短时间内进行锁定和释放。M......
  • 【CF1374E1】Reading Books (easy version)(贪心)
    题目大意:给出\(n(1\len\le2\times10^{5})\)个三元组\((t,a,b)(0\lea,b\le1)\),选出其中任意个,使得被选中的元素\(a\)、\(b\)的总和均为\(k\),求\(t\)总和的最小值因为被选中的元素\(a\)、\(b\)的总和均为\(k\),所以被选中的三元组中,形式为\((t,1,0)\)和\((t,0,1)\)的数量相等......