委托和事件详解

委托和事件详解

  • 前言
  • 一、委托
    • 1.什么是委托
    • 2.委托的声明
    • 3.Action<T>委托和Func<T>委托
    • 4.委托的缺点
    • 5.委托与lambda表达式
    • 6.委托的使用
      • (1)模板方法
      • (2)回调方法
  • 二、事件
    • 1.什么是事件
    • 2.事件模型的5个步骤和组成部分
      • (1)5个步骤
      • (2)5个组成部分
    • 3.实际案例
    • 4.事件语法
    • 5.事件是基于委托的
    • 6.Q&A


前言

这篇委托和事件的学习笔记是基于b站BeaverJoe大佬的视频学习整理的,老师主页还有很多案例教程可供学习~BeaverJoe主页链接


一、委托

1.什么是委托

委托是一种类,引用类型的数据类型。它有返回值类型和参数列表,可以指向一个或多个方法。
当实例化委托后(即创建了一个委托的实例),这个委托类型的实例可以和任何其他方法关联起来,存储这些方法(即 目标方法)的引用(前提是类型兼容),接着就可以通过委托类型的实例 间接调用这些存储的方法(invoke)

2.委托的声明

委托虽然是一种类,但它的声明格式却更接近于方法(这是因为仿造了c语言中函数指针的声明方式)。委托可以声明在类中,因为c#支持嵌套类,此时委托就是一个类的嵌套类。
在这里插入图片描述
【注1】可以省略写法(直接将方法赋值给委托类型变量):

//多播委托
myDelegate+=ChangeColor;
myDelegate+=Log;

【注2】封装的是有参数列表的方法的话,在调用委托时就要传入参数:

myDelegate01("James",3);
myDelegate01("Curry",3);

【注3】自定义声明委托时需要加上delegate关键词,但不是所有委托声明都需要使用delegate关键词,因为c#类库中已经准备好了两个委托Action和Func

3.Action委托和Func委托

可以省去声明委托类型的步骤,直接使用内置委托类型来声明创建变量。
【注】使用时要引入命名空间System
Action< T >: 指向返回值为空,参数列表为空或者有参数列表(最多16个参数)的方法
在这里插入图片描述
Func< T >:指向有返回值,参数列表为空或者有参数列表(最多16个参数)的方法,且返回值一定要放在<>中最后一位
在这里插入图片描述

4.委托的缺点

(1)安全性上:即使可以通过多播委托来调用很多其他的方法,但也是很不安全的,如果把+=写成了=,就覆盖了之前的所有方法,提高了项目维护成本。
(2)关于内存泄漏:委托会引用一个方法,如果这个方法是一个实例方法(非静态方法)的话,那么这个方法就一定隶属于一个对象,拿一个委托引用这个方法,那么这个对象就必须存在在内存中,即使没有其他引用变量引用这个对象了,这个对象的内存也不能被释放。因为一旦释放内存,委托就不能再间接调用对象的方法了,所以说委托容易造成内存泄漏(memory leak),随着内存泄漏越来越多,程序就会面临崩溃。
(3)可读性上:如果在委托内部又嵌套了别的委托,debug难度就会上升,可读性也较差了。

5.委托与lambda表达式

未使用lambda表达式前:
在这里插入图片描述
使用lambda表达式:
lambda表达式真正的作用就是可以省去【创建方法】这一步骤,将Lambda表达式作为一个实际参数,传递到方法中
在这里插入图片描述

6.委托的使用

(1)模板方法

类可以作为方法的参数类型,而委托是一种类,所以可以把委托当作方法的参数,将指向的目标方法传递到另一个方法中去,就形成了一种动态调用方法的代码结构(根据不同的游戏需求,传递不同的委托类型封装的方法,达到动态调用的效果)。
而模板方法就是有一处不确定,其余代码都是确定好的,这个不确定的部分,就靠我们传进来的委托类型的参数所包含的这个方法来填补。

(2)回调方法

所谓的回调关系:某个方法,可以去调用它,也可以不去调用它,用得着的时候就去调用这个方法。
以回调方法形式使用【委托】,需要把委托类型作为参数传入到方法中,被传进方法的委托类型参数内部封装了一个被回调的方法,也就是回调方法,我们的方法会根据自己的逻辑来决定是不是要调用这个回调方法。
【注】一般回调方法都会放在方法代码的末尾之处,且一般回调方法都是没有返回值的
在这里插入图片描述

二、事件

1.什么是事件

事件的定义:当某件有趣的事情发生时,一个类或者对象中的事件就会通知(关心这件事情的)别的类、别的对象“这里有件有趣的事情发生啦!”,别的类、别的对象就会纷纷做出各自的响应
【注】事件必定是一个对象、类的成员,就像“死亡”必须基于“玩家”/“敌人”,“开花”必须基于“花”,“发布”必须基于“新游戏”一样,事件可以“发生”,核心功能是通知别人,发生效果。

2.事件模型的5个步骤和组成部分

(1)5个步骤

事件模型包含5个步骤:
Step1:我(类)要有一个事件(成员)
Step2:一群别的类关心、订阅我的事件
Step3:我的事件发生了!
Step4:关心的类们被一次性通知到
Step5:被通知到的人,拿着事件参数,做出响应

(2)5个组成部分

A、事件的拥有者: 事件的源头,事件的拥有者一定是一个类(或者说是对象),谁拥有事件,谁就是事件的拥有者

B、事件: 一个类的成员类型,是一种让【事件的拥有者】具有通知能力的成员。事件不会主动发生,一定是由事件拥有者的内部逻辑触发

C、事件的响应者: 订阅事件的类、对象们

D、事件处理器: 通过通知和事件参数,而采取行动的行为称为“响应事件”或者“处理事件”,而处理事件时具体做的这些事情(事件响应者处理事件的方法成员),就叫做“事件处理器(EventHandler)”
【注】所谓的约定,就是指这个方法必须和声明事件的时候,会使用的委托类型相匹配(事件基于委托)

E、事件订阅(+=操作符): 事件处理器的【返回值】和【参数列表】必须和事件的【委托类型】保持一致
【注】事件有订阅,就一定有取消订阅,两者是配套出现的,以防内存泄漏的问题
在这里插入图片描述

3.实际案例

在这里插入图片描述

4.事件语法

自定义事件声明格式(完整 / 简略形式)
完整声明格式:
在这里插入图片描述
简略声明格式:(像委托类型字段但不是,事件的本质是委托类型字段的包装器,限制了外部对内部的委托字段的访问,只让访问+=和-=两个操作,而不能直接调用)
在这里插入图片描述
优化后:
在这里插入图片描述

5.事件是基于委托的

【事件是基于委托的】有两层意思:
(1)类型兼容。 事件需要委托类型来做一个约束,这个约束既规定了事件它能发送什么样的消息给事件响应者,同时也规定了事件响应者能收到什么样的消息。事件处理器的【返回值】和【参数列表】必须和事件的【委托类型】保持一致,才能订阅这个事件
(2)存储方法的引用。 当事件的响应者向事件的拥有者提供了一个与之匹配事件的事件处理器之后,就需要一个地方,把这个事件处理器以及之后这些事件处理器保存、储存、记录下来,而只有委托类型的实例能办到这点。

6.Q&A

Q:委托和事件的关系是什么?
A:事件不是特殊的委托类型字段,它只是委托类型字段的包装器,限制外界对委托类型的字段的访问,外界只能去访问他的+=、-=操作符(只能添加/移除事件处理器)

Q:为什么要使用委托类型来声明事件?(换句话说:为什么事件是基于委托的?)
A:当事件的响应者向事件的拥有者提供了一个与之匹配事件的事件处理器之后,就需要一个地方,把这个事件处理器以及之后这些事件处理器保存、储存、记录下来,而只有委托类型的实例能办到这点。

请添加图片描述

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

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

相关文章

《Git 简易速速上手小册》第5章:高级 Git 技巧(2024 最新版)

文章目录 5.1 交互式暂存5.1.1 基础知识讲解5.1.2 重点案例&#xff1a;为 Python 项目分阶段提交5.1.3 拓展案例 1&#xff1a;细粒度控制更改5.1.4 拓展案例 2&#xff1a;处理遗漏的更改 5.2 使用 Rebase 优化提交历史5.2.1 基础知识讲解5.2.2 重点案例&#xff1a;整理 Pyt…

springcloud分布式架构网上商城源码和论文

首先,论文一开始便是清楚的论述了系统的研究内容。其次,剖析系统需求分析,弄明白“做什么”,分析包括业务分析和业务流程的分析以及用例分析,更进一步明确系统的需求。然后在明白了系统的需求基础上需要进一步地设计系统,主要包罗软件架构模式、整体功能模块、数据库设计。本项…

H12-821_35

35.如图所示,SWA、SWB、SWC都运行RSTP,SWB上的GEO/O/2端口和SWC上的GEO/0/1端其端口角色为? A.backup端口.Alternative端口 B.Alternative端口、Backup端口 C.Root端口、Designate端口 D.Backup端口、Root端口 答案&#xff1a;A 注释&#xff1a; 一个链路&#xff08;冲突域…

hexo部署到gitee(码云)

引言 Hexo 是一个基于Node.js的静态博客框架&#xff0c;而 Gitee&#xff08;也被称为码云&#xff09;是一个国内的代码托管平台&#xff0c;支持 Git 版本控制系统&#xff0c;与 GitHub 类似。将 Hexo 部署到 Gitee Pages 可以让你的博客受益于 Gitee 的国内服务器&#xf…

python web 框架Django学习笔记

2018年5月 python web 框架Django学习笔记 Django 架站的16堂课 MVC架构设计师大部分框架或大型程序项目中一种软件工程的架构模式&#xff0c;把程序或者项目分为三个主要组成部分&#xff0c;Model数据模型、View视图、Controller控制器。 命令及设置相关 创建数据库及中间…

Open CASCADE学习|保存为STL文件

STL (Stereolithography) 文件是一种广泛用于3D打印和计算机辅助设计 (CAD) 领域的文件格式。它描述了一个三维模型的表面而不包含颜色、材质或其他非几何信息。STL文件通常用于3D打印过程中&#xff0c;因为它们仅包含构建物体所需的位置信息。 由于STL文件只包含表面信息&am…

《动手学深度学习(PyTorch版)》笔记8.4

注&#xff1a;书中对代码的讲解并不详细&#xff0c;本文对很多细节做了详细注释。另外&#xff0c;书上的源代码是在Jupyter Notebook上运行的&#xff0c;较为分散&#xff0c;本文将代码集中起来&#xff0c;并加以完善&#xff0c;全部用vscode在python 3.9.18下测试通过&…

分布式搜索引擎 elasticsearch

分布式搜索引擎 elasticsearch 第一部分 1.初识elasticsearch 1.1.了解ES 1.1.1.elasticsearch的作用 elasticsearch是一款非常强大的开源搜索引擎&#xff0c;具备非常多强大功能&#xff0c;可以帮助我们从海量数据中快速找到需要的内容 例如&#xff1a; 在GitHub搜索…

LeetCode 0094.二叉树的中序遍历:递归/迭代(栈模拟递归)

【LetMeFly】94.二叉树的中序遍历&#xff1a;递归/迭代(栈模拟递归) 力扣题目链接&#xff1a;https://leetcode.cn/problems/binary-tree-inorder-traversal/ 给定一个二叉树的根节点 root &#xff0c;返回 它的 中序 遍历 。 示例 1&#xff1a; 输入&#xff1a;root […

【Qt 学习之路】在 Qt 使用 ZeroMQ

文章目录 1、概述2、ZeroMQ介绍2.1、ZeroMQ 是什么2.2、ZeroMQ 主线程与I/O线程2.3、ZeroMQ 4种模型2.4、ZeroMQ 相关地址 3、Qt 使用 ZeroMQ3.1、下载 ZeroMQ3.2、添加 ZeroMQ 库3.3、使用 ZeroMQ3.4、相关 ZeroMQ 案例 1、概述 今天是大年初一&#xff0c;先给大家拜个年&am…

我主编的电子技术实验手册(03)——电阻的识别与测量

本专栏是笔者主编教材&#xff08;图0所示&#xff09;的电子版&#xff0c;依托简易的元器件和仪表安排了30多个实验&#xff0c;主要面向经费不太充足的中高职院校。每个实验都安排了必不可少的【预习知识】&#xff0c;精心设计的【实验步骤】&#xff0c;全面丰富的【思考习…

《零基础实践深度学习》实践导学 01

1.1前言 一、课程介绍 《零基础实践深度学习》&#xff08;第1版&#xff09;2020年正式上线&#xff0c;深受开发者和高校师生追捧&#xff0c;累积学习人数超过9万人。本课程是它的升级版&#xff0c;结合深度学习技术的发展、学员反馈&#xff0c;并结合近两年AI产业应用经…

Docker容器化K8s集群部署教程(一键部署sheel脚本)

本文通过脚本&#xff0c;可以快速地部署和配置Kubernetes环境&#xff0c;省去了各插件手动部署、配置的繁琐过程。 先看最终结果&#xff1a; [rootlocalhost home]# kubectl get node NAME STATUS ROLES AGE VERSION k8smaster Ready control-p…

相机图像质量研究(11)常见问题总结:光学结构对成像的影响--像差

系列文章目录 相机图像质量研究(1)Camera成像流程介绍 相机图像质量研究(2)ISP专用平台调优介绍 相机图像质量研究(3)图像质量测试介绍 相机图像质量研究(4)常见问题总结&#xff1a;光学结构对成像的影响--焦距 相机图像质量研究(5)常见问题总结&#xff1a;光学结构对成…

C# OCR识别图片中的文字

1、从NuGet里面安装Spire.OCR 2、安装之后&#xff0c;找到安装路径下&#xff0c;默认生成的packages文件夹&#xff0c;复制该文件夹路径下的 6 个dll文件到程序的根目录 3、调用读取方法 OcrScanner scanner new OcrScanner(); string path "C:\1.png"; scann…

算法学习——LeetCode力扣二叉树篇2

算法学习——LeetCode力扣二叉树篇2 107. 二叉树的层序遍历 II 107. 二叉树的层序遍历 II - 力扣&#xff08;LeetCode&#xff09; 描述 给你二叉树的根节点 root &#xff0c;返回其节点值 自底向上的层序遍历 。 &#xff08;即按从叶子节点所在层到根节点所在的层&#…

JAVA反射总结学习

初始反射反射的基本操作反射安全性问题 反射是指在Java运行状态中: 给定一个类对象(Class对象)&#xff0c;通过反射获取这个类对象(Class对象)的所有成员结构&#xff1b; 给定一个具体的对象&#xff0c;能够动态地调用它的方法及对任意属性值进行获取和赋值&#xff1b; …

Popper.js:ElementUI 中采用弹出,提示框库,好用的没朋友。

Hi&#xff0c;我贝格前端工场&#xff0c;继续介绍经典的js库&#xff0c;ElementUI 中Tooltip、Select、Cascader、TimePicker等组件中怎么把提示框定位到目标元素的&#xff0c;是用 Popperjs 来实现。 一、Popper.js是什么&#xff1f; Popper.js是一个用于创建弹出式组件…

Duilib List 控件学习

这是自带的一个示例; 一开始运行的时候List中是空的,点击Search按钮以后就填充列表框; 先看一下列表框列头是在xml文件中形成的; <List name="domainlist" bkcolor="#FFFFFFFF" ... menu="true"> <ListHeader height="24…

MATLAB知识点: ismember函数 判断数组A中的元素是否在数组B中

​讲解视频&#xff1a;可以在bilibili搜索《MATLAB教程新手入门篇——数学建模清风主讲》。​ MATLAB教程新手入门篇&#xff08;数学建模清风主讲&#xff0c;适合零基础同学观看&#xff09;_哔哩哔哩_bilibili 节选自第3章 3.4.5 集合运算 h ismember(A, B)可以判断数组…