C#——Delegate(委托)与Event(事件)

news2025/6/17 13:06:29

C#——Delegate(委托)与Event(事件)

  • 前言
  • 一、Delegate(委托)
    • 1.是什么?
    • 2.怎么用?
      • Example 1:无输入无返回值
      • Example 2:有输入
      • Example 3:有返回值
      • Example 4:多播委托
      • Example 5:处理有返回值的多播委托的结果
  • 二、Event(事件)
    • 1.是什么?
    • 2.怎么用?
      • Example 1:简单案例
      • Example 2:流程中重复绑定同一方法的优化
  • 三、总结


前言

在刚开始学习C#的时候,常常委托与事件傻傻分不清,经常性的混为一谈。他们功能相似,应用场景却不太一样,下面就从分别的介绍再到差异的分析一起来看看啪。

一、Delegate(委托)

1.是什么?

委托是 C# 中的一种类型,它代表了对一个或多个方法的引用。它类似于函数指针,在编程中可以将方法作为参数传递给其他方法。

2.怎么用?

看个简单的委托应用:

例子是基于C#控制台编写的

Example 1:无输入无返回值

申明委托类型:

delegate void write();

定义一个委托变量:

        static write w;

写一个和申明的委托变量相同输入输出类型的函数:

        public static void writeS()
        {
            Console.WriteLine(1);
        }

给委托绑定方法并调用:

        static void Main(string[] args)
        {
            w += writeS;  //绑定
            w();		  //调用,会运行绑定的方法(writeS)
            Console.ReadKey();
        }

结果:
直接打印一个1。
在这里插入图片描述

Example 2:有输入

申明委托类型:

delegate void write(int a,int b);

定义一个委托变量:

        static write w;

写一个和申明的委托变量相同输入输出类型的函数:

        public static void writeS(int a,int b)
        {
            Console.WriteLine(a + b);
        }

给委托绑定方法并调用:

        static void Main(string[] args)
        {
            w += writeS;  //绑定
            w(1,2);		  //调用,会运行绑定的方法(writeS)
            Console.ReadKey();
        }

结果:
直接打印一个3。
在这里插入图片描述

Example 3:有返回值

申明委托类型:

delegate bool write(int a,int b);

定义一个委托变量:

        static write w;

写一个和申明的委托变量相同输入输出类型的函数:

        public static bool writeS(int a,int b)
        {
            return a > b;
        }

给委托绑定方法并调用:

        static void Main(string[] args)
        {
            w += writeS;  //绑定
            Console.WriteLine( w(1,2));		  //调用,会运行绑定的方法(writeS)
            Console.ReadKey();
        }

结果:
直接打印一个False。
在这里插入图片描述

Example 4:多播委托

在此讨论比较特殊的有返回值的多播委托
简单理解,就是把多个方法绑定到一个委托,委托触发将触发所有绑定的方法。

申明委托类型:

delegate bool write(int a,int b);

定义一个委托变量:

        static write w;

写一个和申明的委托变量相同输入输出类型的函数:

        public static bool writeS(int a,int b)
        {
            return a > b;
        }
        
        public static bool writeS2(int a,int b)
        {
            return a < b;
        }

给委托绑定方法并调用:

        static void Main(string[] args)
        {
            w += writeS;  //绑定
            w += writeS2;  //绑定
            Console.WriteLine( w(1,2));		  //调用,会运行绑定的方法(writeS和writeS2)
            Console.ReadKey();
        }

结果:
直接打印一个True。
在这里插入图片描述

此时可以注意到,我绑定了两个带返回值的方法,第一个(writeS)返回false,第二个(writeS2)返回true。实际页面打印的是True。多次测试后可以发现,当多播委托带有返回值时且有多个绑定方法时,返回值将以最后一个添加绑定的为最终结果。

Example 5:处理有返回值的多播委托的结果

为解决Example4中绑定多个返回值的方法时,可以在外部进行数据分析来获取最终的结果。

新增代码如下:

        static bool JudgeRet(int a,int b)
        {
            bool ret = true;
            if (w != null)
            {
                foreach (write item in w.GetInvocationList())//变量委托里面的所有绑定的方法列表,获取结果并处理结果
                {
                    ret = ret & item(a,b);//处理流程,有false就为false。
                }
            }
            return ret;
        }

完整代码如下:

    class Program
    {
        delegate bool write(int a,int b);
        static write w;
        static void Main(string[] args)
        {
            w += writeS;
            w += writeS2;
            Console.WriteLine(JudgeRet(1,2));
            Console.ReadKey();
        }

        static bool JudgeRet(int a,int b)
        {
            bool ret = true;
            if (w != null)
            {
                foreach (write item in w.GetInvocationList())
                {
                    ret = ret & item(a,b);
                }
            }
            return ret;
        }

        public static bool writeS(int a,int b)
        {
            return a > b;
        }

        public static bool writeS2(int a, int b)
        {
            return a < b;
        }
    }

结果:
有false则为false。
在这里插入图片描述

二、Event(事件)

1.是什么?

事件是一种特殊类型的委托,用于实现观察者模式。它限制了委托的使用,只允许外部类通过 += 和 -= 运算符订阅和取消订阅事件。它提供了一种安全的订阅机制,防止外部类直接调用委托列表。只有持有类可以触发事件。

本质上:事件是对委托的封装,提供了一种更安全、更封装的方式来进行观察者模式的实现。

2.怎么用?

Example 1:简单案例

全部代码以及解析:

    public delegate bool write(int a, int b);  //定义的委托类型

    public class test							//测试类,体现事件只能在持有类中触发
    {
        write w;								//委托对象

        public event write WriteEvent;			//事件对象
        
        public void triger(int a, int b)		//触发事件
        {
            WriteEvent?.Invoke(a, b);			//判断事件是否为空,不为空则触发
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            test t = new test();				//生成测试类实例
            //此时在外部,无法访问到委托实例w,只能通过事件WriteEvent绑定
            t.WriteEvent += writeS;				//绑定方法
            t.WriteEvent += writeS;
            t.WriteEvent += writeS;				//绑定了多次相同的方法
            t.WriteEvent += writeS;

            t.triger(1, 2);						//触发

            Console.ReadKey();
        }

        public static bool writeS(int a, int b)
        {
            Console.WriteLine(a + b);
            return a > b;
        }
    }

结果如下:

发现多次绑定同一方法时,无法判断重复,绑定几次执行几次。
在这里插入图片描述

上文需要注意的是,WriteEvent?.Invoke(a, b);直接调用了事件名,在简略声明中,可以 使用Invoke调用事件,但也仅限于事件拥有类内部使用。

Example 2:流程中重复绑定同一方法的优化

优化事件代码如下:

    public delegate bool write(int a, int b);

    public class test
    {
        write w;

        public event write WriteEvent
        {
            add
            {
                if (w != null && w.GetInvocationList().Contains(value))
                {
                    return;
                }
                w += value;
            }
            remove
            {
                w -= value;
            }
        }

        public void triger(int a, int b)
        {
            w(a, b);							//此处因为重写了Add以及Remove无法使用WriteEvent?.Invoke(a, b);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            test t = new test();
            t.WriteEvent += writeS;
            t.WriteEvent += writeS;
            t.WriteEvent += writeS;
            t.WriteEvent += writeS;
            t.triger(1, 2);
            Console.ReadKey();
        }

        public static bool writeS(int a, int b)
        {
            Console.WriteLine(a + b);
            return a > b;
        }
    }

结果:
在这里插入图片描述

三、总结

简单点:

  • 委托允许你将方法作为参数传递或存储,可以被直接调用。
  • 事件是一种特殊类型的委托,提供更安全、封装的订阅机制,只允许持有类触发事件(且必须是简单声明)。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

实现数据一体化的有效措施

数据一体化的趋势 数据一体化是指将企业内部和外部的各种数据资源整合、统一管理和共享利用的过程&#xff0c;是当前信息化发展的重要趋势。 统一数据平台&#xff1a;企业越来越意识到数据是重要资产&#xff0c;需要建立统一的数据平台&#xff0c;集中管理和利用各类数据资…

直击广州车展 | 远航汽车“卷”出新高度

第23届广州车展作为2023年汽车行业的年度收官之作&#xff0c;成为各大汽车厂商“秀肌肉”的绝佳舞台&#xff0c;22万平方米的开放展区内容纳了1132辆展车&#xff0c;包括全球首发车59辆、概念车20辆、新能源车469辆。 新能源汽车产业发展迅猛&#xff0c;得益于新能源车型在…

开源vs闭源,大模型的未来在哪一边?

开源和闭源&#xff0c;两种截然不同的开发模式&#xff0c;对于大模型的发展有着重要影响。开源让技术共享&#xff0c;吸引了众多人才加入&#xff0c;推动了大模的创新。而闭源则保护了商业利益和技术优势&#xff0c;为大模型的商业应用提供了更好的保障。 那么&#xff0c…

Android-P CameraSerivce

0 前言 本文重点分析Android-P的CameraService实现。 验证:Goldfish模拟器 1 定义 图1.1 CameraService ICameraServiceframeworks/av/camera/aidl/android/hardware/ICameraService.aidlBnCameraServiceout/soong/.intermediates/frameworks/av/camera/libcamera_client/an…

如何远程开关机电脑丨远程开关机电脑的小技巧

在日常生活和工作中&#xff0c;我们可能需要远程控制电脑的开关机。下面就介绍几种常用的远程开关机方法。 方法一&#xff1a; 一、自行下载域之盾软件 https://www.yuzhidun.cn/https://www.yuzhidun.cn/ 二、在一台老板电脑上部署管理端&#xff0c;在想要远程开关机的电…

03、K-means聚类实现步骤与基于K-means聚类的图像压缩(2)

03、K-means聚类实现步骤与基于K-means聚类的图像压缩&#xff08;2&#xff09; 工程下载&#xff1a;K-means聚类实现步骤与基于K-means聚类的图像压缩 其他&#xff1a; 03、K-means聚类实现步骤与基于K-means聚类的图像压缩&#xff08;1&#xff09; 03、K-means聚类实现…

day66

今日回顾内容 web框架 django 路由控制 视图层 web框架 一、什么是web框架 Web框架&#xff08;Web framework&#xff09;是一种开发框架&#xff0c;用来支持动态网站、网络应用和网络服务的开发。这大多数的web框架提供了一套开发和部署网站的方式&#xff0c;也为web行…

从0开始学习JavaScript--JavaScript中的解构赋值及使用场景

在现代JavaScript中&#xff0c;解构赋值是一种强大而灵活的语法特性&#xff0c;它允许从数组或对象中提取值并赋给变量。这种语法不仅使代码更简洁&#xff0c;而且提高了可读性。在本篇文章中&#xff0c;将深入探讨JavaScript中解构赋值的基本概念、语法规则以及丰富的使用…

element-plus 使用密码输入框的自定义图标

<el-inputv-model"ruleFormPassword.newPassword"placeholder"请输入新密码":type"showPassword ? text : password":style"{ width: 360px }"><template #suffix><span class"input_icon" click"swit…

JavaScript基础—函数、参数、返回值、作用域、变量、匿名函数、综合案例—转换时间,逻辑中断,转换为Boolean型

版本说明 当前版本号[20231129]。 版本修改说明20231126初版20231129完善部分内容 目录 文章目录 版本说明目录JavaScript 基础 - 第4天笔记函数声明和调用声明&#xff08;定义&#xff09;调用细节补充 参数形参和实参函数默认值 返回值作用域全局作用域局部作用域 变量全…

【论文阅读】基于隐蔽带宽的汽车控制网络鲁棒认证(三)

文章目录 第六章 通过认证帧定时实现VulCAN的非once同步6.1 问题陈述6.2 方法概述6.3 动机和缺点6.3.1 认证帧定时隐蔽通信6.3.2 VulCAN的梵蒂冈后端Nonce同步的应用 6.4 设计与实现6.4.1发送方6.4.2 接收方6.4.3 设计参数配置6.4.4 实现 6.5 安全注意事项6.5.1 系统模型6.5.2攻…

提升认知|为什么比尔盖茨在地上发现100美元也会捡?

哈喽呀&#xff0c;大家好&#xff0c;我是雷工&#xff01; 大概在高中时代&#xff0c;听到过这么一个段子&#xff0c;“说如果地上有100美元&#xff0c;比尔盖茨是不会去捡的&#xff0c;因为他弯腰去捡100美元浪费的时间足够其创造1000美元以上的价值。” 当时听完也觉得…

场景应用丨厦门水环境综合治理监测系统效果和作用

厦门&#xff0c;这座美丽的海滨城市&#xff0c;其水资源的状况与水环境的治理对于城市的生存与发展至关重要。近年来&#xff0c;厦门致力于打造生态宜居的城市环境&#xff0c;对城市生命线——水资源的保护与治理给予了极大的关注。其中&#xff0c;水资源综合治理监测系统…

贝锐向日葵与华为达成合作,启动鸿蒙原生应用开发

2023年11月24日&#xff0c;贝锐与华为携手举办鸿蒙原生应用开发启动仪式。贝锐创始人之一兼首席技术官张小峰先生、贝锐事业部总经理张海英女士共同出席了此次活动&#xff0c;并达成重大合作。贝锐旗下国民级远程控制品牌贝锐向日葵将以原生方式适配鸿蒙系统&#xff0c;成为…

《软件工程原理与实践》复习总结与习题——软件工程

软件生命周期 软件生命周期分为三个时期、八个阶段 软件定义时期&#xff1a; 1&#xff09;问题定义阶段&#xff1a;要解决什么问题 2&#xff09;可行性研究阶段&#xff1a;确定软件开发可行 3&#xff09;需求分析阶段&#xff1a;系统做什么 软件开发时期&#xff1a;…

查理·芒格之死对伯克希尔·哈撒韦公司意味着什么?

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 虽然查理芒格是伯克希尔哈撒韦公司首席执行官沃伦巴菲特的重要合作伙伴&#xff0c;但猛兽财经认为查理芒格的去世并不会对伯克希尔哈撒韦的正常运营产生太大的影响&#xff0c;因为该公司长期以来一直是由巴菲特主导的。 …

YouTube宣布要求披露AI生成的内容并添加标签

不知道大家在逛YouTube的时候有没有刷到过一些画面和人物看起来不太自然的视频。 没错&#xff0c;这些视频里面的画面和人物可能都是由AI生成的。 近日&#xff0c;YouTube 产品管理副总裁在官方博客文章上表示&#xff1a;生成式 AI 有潜力在 YouTube 上激发创造力&#xff…

vue2常见的语法糖

Vue.js 2 提供了一些语法糖&#xff08;syntactic sugar&#xff09;来简化常见的操作。以下是一些 Vue.js 2 中常用的语法糖&#xff1a; v-bind 简写&#xff1a; <!-- 完整语法 --> <a v-bind:href"url">Link</a><!-- 简写 --> <a :hr…

解决:ValueError: must have exactly one of create/read/write/append mode

解决&#xff1a;ValueError: must have exactly one of create/read/write/append mode 文章目录 解决&#xff1a;ValueError: must have exactly one of create/read/write/append mode背景报错问题报错翻译报错位置代码报错原因解决方法今天的分享就到此结束了 背景 在使用…

初学者如何理解​session、cookie、token的区别与联系?

session、cookie、token。 相信学过接口的朋友都特别熟悉了。 但是对我一个刚接触接口测试的小白来说&#xff0c;属实有点分不清楚。 下文就是我通过查阅各种资料总结出来的一点理解&#xff0c;不准确的地方还请各位指正。 &#xff08;文末送洗浴中心流程指南&#xff09…