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

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.mzph.cn/news/192689.shtml

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

相关文章

【C#】接口定义和使用知多少

给自己一个目标&#xff0c;然后坚持一段时间&#xff0c;总会有收获和感悟&#xff01; 最近在封装和参考sdk时&#xff0c;看到一个不错的写法&#xff0c;并且打破自己对接口和实现类固定的观念&#xff0c;这也充分说明自己理解掌握的知识点还不够深。 目录 前言一、什么是…

Kubernetes(K8s)_16_CSI

Kubernetes&#xff08;K8s&#xff09;_16_CSI CSICSI实现CSI接口CSI插件 CSI CSI(Container Storage Interface): 实现容器存储的规范 本质: Dynamic Provisioning、Attach/Detach、Mount/Unmount等功能的抽象CSI功能通过3个gRPC暴露服务: IdentityServer、ControllerServe…

C++二维数组名到底代表个啥

题目先导 int a[3][4]; 则对数组元素a[i][j]正确的引用是*(*(ai)j)先翻译一下这个*(*(ai)j)&#xff0c;即a后移i解引用&#xff0c;再后移j再解引用&#xff0c;这么看来a就应该是个二维数组&#xff0c;第一层存储行向量&#xff0c;一次解引用获得行向量的地址&#xff0c;…

LLM推理部署(三):一个强大的LLM生态系统GPT4All

GPT4All&#xff0c;这是一个开放源代码的软件生态系&#xff0c;它让每一个人都可以在常规硬件上训练并运行强大且个性化的大型语言模型&#xff08;LLM&#xff09;。Nomic AI是此开源生态系的守护者&#xff0c;他们致力于监控所有贡献&#xff0c;以确保质量、安全和可持续…

听GPT 讲Rust源代码--src/tools(6)

File: rust/src/tools/rust-analyzer/crates/ide/src/references.rs 在Rust源代码中&#xff0c;references.rs文件位于rust-analyzer工具的ide模块中&#xff0c;其作用是实现了用于搜索引用的功能。 该文件包含了多个重要的结构体、特质和枚举类型&#xff0c;我将逐一介绍它…

node.js-连接SQLserver数据库

1.在自己的项目JS文件夹中建文件&#xff1a;config.js、mssql.js和server.js以及api文件夹下的user.js 2.在config.js中封装数据库信息 let app {user: sa, //这里写你的数据库的用户名password: ,//这里写数据库的密码server: localhost,database: medicineSystem, // 数据…

OpenSSH 漏洞修复升级最新版本

Centos7系统ssh默认版本一般是OpenSSH7.4左右&#xff0c;低版本是有漏洞的而且是高危漏洞&#xff0c;在软件交付和安全扫描上是过不了关的&#xff0c;一般情况需要升级OpenSSH的最新版本 今天详细说下升级最新版本的处理过程&#xff08;认真看会发现操作很简单&#xff0c…

Best Rational Approximation ——二分

许多微控制器没有浮点单元&#xff0c;但确实有一个&#xff08;合理&#xff09;快速整数除法单元。在这些情况下&#xff0c;使用有理值来近似浮点常数可能是值得的. 例如&#xff0c;355/113 3.1415929203539823008849557522124 是 π 3.14159265358979323846 一个很好的近…

【教学类-06-12】20231202 0-9数字分合-房屋样式(一)-下右空-升序-抽7题

作品展示-屋顶分合&#xff08;0-9之间随机抽取7个不重复分合&#xff09; 背景需求&#xff1a; 大班幼儿学分合题&#xff0c;通常区角里会设计一个“房屋分合”的样式 根据这种房屋样式&#xff0c;设计0-9内的升序分合题模板 素材准备 WORD样式 代码展示&#xff1a; 2-9…

PlantUML语法(全)及使用教程-用例图

目录 1. 用例图1.1、什么是用例图1.2、用例图的构成1.3、参与者1.4、用例1.4.1、用例基本概念1.4.2、用例的识别1.4.3、用例的要点1.4.3、用例的命名1.4.4、用例的粒度 1.5、应用示例1.5.1、用例1.5.2、角色1.5.3、改变角色的样式1.5.4、用例描述1.5.5、改变箭头方向1.5.6、使用…

AI创作ChatGPT源码+AI绘画(Midjourney绘画)+DALL-E3文生图+思维导图生成

一、AI创作系统 SparkAi创作系统是基于ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如何搭建部署AI…

C语言——指针(四)

&#x1f4dd;前言&#xff1a; 上篇文章C语言——指针&#xff08;三&#xff09;对指针和数组进行了讲解&#xff0c;今天主要更深入的讲解一下不同类型指针变量的特点&#xff1a; 1&#xff0c;字符指针变量 2&#xff0c;数组指针变量 3&#xff0c;函数指针变量 &#x1…

Spring boot命令执行 (CVE-2022-22947)漏洞复现和相关利用工具

Spring boot命令执行 (CVE-2022-22947)漏洞复现和相关利用工具 名称: spring 命令执行 (CVE-2022-22947) 描述: Spring Cloud Gateway是Spring中的一个API网关。其3.1.0及3.0.6版本&#xff08;包含&#xff09;以前存在一处SpEL表达式注入漏洞&#xff0c;当攻击者可以访问A…

2022年8月2日 Go生态洞察:Go 1.19版本发布深度解析

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

6-63.圆类的定义与使用(拷贝构造函数)

本题要求完成一个圆类的定义&#xff0c;设计适当的函数&#xff1a;包括构造函数、拷贝构造函数以及析构函数&#xff0c;从而可以通过测试程序输出样例 在这里给出一组输入。例如&#xff1a; 5 输出样例&#xff1a; 在这里给出相应的输出。例如&#xff1a; Constructo…

本项目基于Spring boot的AMQP模块,整合流行的开源消息队列中间件rabbitMQ,实现一个向rabbitMQ

在业务逻辑的异步处理&#xff0c;系统解耦&#xff0c;分布式通信以及控制高并发的场景下&#xff0c;消息队列有着广泛的应用。本项目基于Spring的AMQP模块&#xff0c;整合流行的开源消息队列中间件rabbitMQ,实现一个向rabbitMQ添加和读取消息的功能。并比较了两种模式&…

osg LOD节点动态调度

1、LOD节点 LOD&#xff08;level of detail&#xff09;&#xff1a;是指根据物体模型的结点在显示环境中所处的位置和重要度&#xff0c;决定物体渲染的资源分配&#xff0c;降低非重要物体的面数和细节度&#xff0c;从而获得高效率的渲染运算。在OSG的场景结点组织结构中&…

mongoose学习记录

mongoose安装和连接数据库 npm i mongoose导入mongoose const mongoose require(mongoose) mongoose.set("strictQuery",true)连接数据库 mongoose.connect(mongodb:127.0.0.1:27017/test)设置回调 mongoose.connection.on(open,()>{console.log("连接成…

规则引擎专题---3、Drools组成和入门

Drools概述 drools是一款由JBoss组织提供的基于Java语言开发的开源规则引擎&#xff0c;可以将复杂且多变的业务规则从硬编码中解放出来&#xff0c;以规则脚本的形式存放在文件或特定的存储介质中(例如存放在数据库中)&#xff0c;使得业务规则的变更不需要修改项目代码、重启…

numpy实现神经网络

numpy实现神经网络 首先讲述的是神经网络的参数初始化与训练步骤 随机初始化 任何优化算法都需要一些初始的参数。到目前为止我们都是初始所有参数为0&#xff0c;这样的初始方法对于逻辑回归来说是可行的&#xff0c;但是对于神经网络来说是不可行的。如果我们令所有的初始…