Unity 委托与事件、装箱和拆箱

文章目录

  • 前言
  • 一、委托与事件
    • 1、委托的概念
    • 2、委托是什么
    • 3、事件是什么
  • 二、装箱和拆箱
    • 1、什么是装箱和拆箱
    • 2、堆、栈
    • 3、应用
    • 4、优化
  • 总结


前言


一、委托与事件

1、委托的概念

不知道大家在学习C#之前有没有学习过C/C++,在中后期会接触到指针。她不仅能指向变量的地址,还能指向函数的地址。本质上,指向的都是内存的地址。
而在C#中,万物皆是类,指针被封装到内部函数中,因此并不常见。所有函数指针的功能都以委托的方式完成。委托可以被视为更高级的函数指针,它不仅能将地址指向另一个函数,而且还能传递参数、获取返回值等多种信息。

委托具有以下属性:
委托类似于 C++ 函数指针,但委托完全面向对象,不像 C++ 指针会记住函数,委托会同时封装对象实例和方法。
委托允许将方法作为参数进行传递。
委托可用于定义回调方法。
委托可以链接在一起;例如,可以对一个事件调用多个方法。
方法不必与委托类型完全匹配。 有关详细信息,请参阅使用委托中的变体。
使用 Lambda 表达式可以更简练地编写内联代码块。 Lambda 表达式(在某些上下文中)可编译为委托类型。 若要详细了解 lambda 表达式,请参阅 lambda 表达式。
官方解释

2、委托是什么

委托并不是一个语言类型,而是一个实例。大多数语言实现delegate关键字 (keyword) ,这些语言的编译器能够派生自 MulticastDelegate 类。MulticastDelegate 类显式Delegate派生。 类 Delegate 不被视为委托类型;它是用于派生委托类型的类。
什么意思呢,我们不能自己写一个类继承MulticastDelegate类,只有编辑器或其他工具可以。
Delegate类中有一个变量是用来存储函数地址的,当变量操作=(等号)时,把函数地址赋值给变量保存起来。不过这个存储函数地址的变量是一个可变数组,你可以认为它是一个链表,每次直接赋值时会换一个链表。 Delegate委托类还重写了+=、-=这两个操作符,其实就是对应MulticastDelegate类的Combine()和Remove()方法,当对函数进行+=和-=操作时,相当于把函数地址推入链表尾部,或者移出链表。
下面是官方的解释,意思是C#编辑器设计了一个列表来执行delegate,虽然我们在代码中使用了 delegate 关键字来定义委托类型,但实际上编译器在编译时会将其重写成 Delegate 类。换句话说,delegate 关键字只是一种修饰用词,用来告诉编译器我们正在定义一个委托类型,但最终在编译后的代码中,委托类型会被转换成一个类,这个类是 System.MulticastDelegate 类的子类。

MulticastDelegate类中有一个已经连接好的delegate列表,被称为调用列表,它由一个或者更多个元素组成。当一个multicast delegate被启动调用时,所有在调用列表里的delegate都会按照它们出现的顺序被调用。如果在执行列表期间遇到一个错误,就会立即抛出异常并停止调用。

3、事件是什么

事件是对委托的再次封装,目的是限制用户直接操作委托实例中的变量。因此,事件不能通过等号(=)赋值,而是只能通过注册和注销方法来增减委托的数量。这种限制的好处是显而易见的:在多人合作开发时,公开的委托很容易被其他人无意覆盖,而事件能更好地维护项目的稳定性和可靠性。

二、装箱和拆箱

1、什么是装箱和拆箱

装箱和拆箱,装箱是指将值类型转换成引用类型,拆箱是指将引用类型转换为值类型。
装箱:

int a = 5;object obj = a;

拆箱:

a = (int)obj;

装箱过程中,a赋值给obj,obj创建一个指针并指向a的数据空间。
拆箱过程中,obj复制一份数据给a。
值类型声明时即初始化自身,不能为null。而引用类分配内存后,不指向任何空间,默认为null。

2、堆、栈

栈是一种特殊的容器,用来存放对象,遵循先进后出的原则。它的存储空间是连续的,因此对栈数据的定位速度比较快。与之相反,堆是随机分配的空间,处理的数据比较多,定位速度较慢。堆内存的创建和删除节点的时间复杂度是O(lgn),而栈的时间复杂度则是O(1),因此栈的速度更快。
尽管栈速度快,但它的生命周期必须确定,销毁时必须按照特定次序进行,即从最后分配的部分开始销毁。因此,栈主要用于生命周期比较确定的场景,如函数调用和递归调用。相反,堆内存可以存放生命周期不确定的内存块,满足需要在需要删除时再删除的需求。因此,堆内存更适合用于存放全局类型的内存块,分配和销毁更加灵活。
但要注意,值类型和引用类型并不是对应栈内存和堆内存。栈内存主要为确定性生命周期的内存服务,堆内存则更多的是无序的随时可以释放的内存。值类型和引用类型能在堆也能在栈内,其中引用类型指针部分可以指向栈内或堆内。

3、应用

在项目中需要一个通用的接口时就需要装箱操作。

4、优化

装箱、拆箱时会不断分配和销毁内存,增减内存碎片。
我们需要尽量少用。怎么做呢。
1、使用泛型。
2、统一接口提前装箱、拆箱。
3、使用Struct时通过重载函数来避免装箱、拆箱。对于值类型(Struct)而言,如果没有重载 ToString() 和 GetType() 等方法,当调用它们时会发生装箱操作。装箱操作会将值类型转换为引用类型(Object 类型),这会导致内存块重新分配,从而带来性能损耗。
书中举例:
如果Struct A和Struct B都继承了接口I,我们调用的方法是void Test(I i)。当调用Test方法时,传进去的Struct A或Struct B的实例相当于提前执行了装箱操作,Test方法里拿到参数后就不用再担心内部再次出现装箱、拆箱的问题了。


总结

在项目中,需要注意委托、装箱与拆箱的使用,尽量避免性能损耗。使用泛型、重载函数、提前装箱等方式进行优化。期待你的精益求精,加油!

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

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

相关文章

FPGA第一篇,FPGA现场可编程门阵列,从0开始掌握可编程硬件开发(FPGA入门指南)

简介:FPGA全称Field-Programmable Gate Array,是一种可编程逻辑器件,它通过可编程的逻辑单元和可编程的连接网络实现了灵活的硬件实现。与固定功能的集成电路(ASIC)相比,FPGA具有更高的灵活性和可重新配置性…

未授权访问:Redis未授权访问漏洞

目录 1、漏洞原理 2、环境搭建 3、未授权访问 4、利用redis未授权写入weshell 5、利用redis未授权反弹shell 6、利用redis未授权实现免密登录 防御手段 从这篇文章开始我就要开始学习各种未授权访问的知识和相关的实操实验了,一共有好多篇,内容主…

美港通正规炒股市场恒生科指半日跌近2% 大型科技股集体下行

查查配5月7日电 7日,港股主要股指回调。截至午盘,恒生指数跌0.85%,恒生科技指数跌1.98%。 美港通证券以其专业的服务和较低的管理费用在市场中受到不少关注。该平台提供了实盘交易、止盈止损、仓位控制等功能,旨在为投资者提供更为全面的投资体验。 来源:Wind 盘面上,零售、软…

OC5864 0.6A输出 60V输入 500KHZ DCDC降压转换IC

一级代理 技术支持 提供样品测试 Tel:18028786817 简介 OC5864是一款内置功率MOSFET的单片降压型开关模式转换器。OC5864在5.5~60V宽输入电源范围内实现0.6A峰值输出电流,并且具有出色的线电压和负载调整率。 OC5864采用PWM电流模工作模式,…

stm32单片机遇到的问题(持续更新)

flymcu下载问题一直显示连接,实际是连接不上 参考,软件一键下载电路等 使用flymcu下载程序过程中,检测两个地方**,第一,两个boot引脚在下载和硬件运行不同的连接方式** BOOT1x,BOOT00:最常用的模…

kubectl_进阶_网络

网络 容器网络发展到现在,形成了两大阵营,就是 Docker 的 CNM 和 Google、CoreOS、Kuberenetes 主导的 CNI。首先明确一点,CNM 和 CNI 并不是网络实现,他们是网络规范和网络体系,从研发的角度他们就是一堆接口&#x…

RPC 失败。curl 16 Error in the HTTP2 framing layer

报错: (base) hh-virtual-machine:~/work$ git clone https://github.com/yangzongzhuan/RuoYi-Vue3.git 正克隆到 RuoYi-Vue3... error: RPC 失败。curl 16 Error in the HTTP2 framing layer fatal: 在引用列表之后应该有一个 flush 包这个错误通常是由于 Git 在…

sql中的lag()和lead()是什么意思

在SQL中,LAG() 和 LEAD() 是窗口函数,它们用于访问行与其相邻行的数据。这两个函数在进行数据比较和分析时非常有用,尤其是在需要根据行的相对位置进行操作的场景中。 ### LAG() LAG() 函数用于访问当前行的前面的行中的数据。你可以指定你想…

CentOS操作

1.如何修改主机名 方法一: 修改命令:hostnamectl set-hostname 主机名 查看命令:hostname 方法二和方法三都是永久改变主机名,需要密码验证 方法二 修改命令:nmcli general hostname 主机名 查看命令&#xff…

了解 websocket

​ 1. 概念 1、 websocket 是一种双向通行协议。实现了浏览器与服务器全双工通信,能更好的节省服务器资源和带宽并达到实时通讯的目的; 2、websocket连接成功后,只要连接不断开,通信就会一保持着; 3、要打开一个 WebS…

三维点云处理-聚类(下)

接着前一部分数据聚类方法的介绍,由于K-means和GMM方法都是基于欧式距离信息处理的,两者分别以圆形和椭圆形来作为数据的聚类分割方式,这种情况下会导致环形图和月牙图数据分割不准确,因此进一步的介绍一种谱聚类方法,…

感知机导论

综述 每一个算法都是为了解决一类问题,或者说是解决之前算法存在的缺陷而产生的,感知机,在这里就起到了一个很大的作用,它向后续的很多算法暴露出来了很多它存在的缺陷。所以我们后面要学习的很多算法都是在某种程度上解决了感知机暴露出来的…

静态NAT

哈喽!各位小伙伴们好久不见,最近由于工作的原因断更了一段时间,不过最近我都会把这些给补上,今天我们来学习一个简单的知识——静态NAT转换。 第一章 什么是NAT技术? 网络地址转换技术NAT(Networ…

致远M3 log 敏感信息泄露漏洞

文章目录 免责漏洞描述漏洞原理影响版本漏洞复现修复方法 免责 只为学习与交流,若利用做一切违法乱纪的事与本人无关 漏洞描述 致远M3是一个企业移动业务管理平台,全面覆盖各种工作场景,通过智能化的办公和业务场景融合,为企业…

【数据库原理及应用】期末复习汇总高校期末真题试卷07

试卷 一、填空题(每空1分,共10分) 1.数据库管理系统在外模式、模式和内模式这三级模式之间提供了两层映象,其中 映象保证了数据的逻辑独立性。 2. 数据模型通常由 、数据操作和完整性约束三部分组…

未来几年,还是要掌握真正的技术

我看到某些人很鼓吹不要精心学技术,要学管理,学系统化的思想方式。这都是在鼓吹成功的玄学,其实成功的人都具备偶然性,换而言之,再给他一次机会,他不见得会赚取这么多的财富。过去几十年,经济高…

SAP FI 常用表

GL部分: FAGLFLEXT 新总账汇总表 GLT0 旧总帐汇总表 SKA1 总账科目主记录 (科目表) 科目表层数据 SKAT 总帐科目主记录(科目表:说明) 包括语言代码 SKB1 总帐科目主记录 (公司代码) 公司代码层数据 BKPF…

代码随想录:二分查找相关题目推荐(35、34)

35.搜索插入位置 题目 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 示例 1: 输入: nums [1,3,5,6], target …

java项目跑不起来 端口已被使用

背景 Springboot项目跑不起来,原因端口被占用。 解决方法 在 Windows 环境下,你可以按照以下步骤来查看某个端口被占用的情况,并停止相应的进程: 查看所有端口占用情况: 按下 Win R 键,打开运行窗口。…

Python调用讯飞星火大模型v3.5接口

在国外,ChatGPT已经成为AI模型行业的大佬,但是国内如果需要使用,会有各种限制,本文介绍如何使用国内的模型。 在国内,讯飞星火大模型是一个非常优秀的中文预训练模型。本文将介绍如何使用Python调用讯飞星火大模型接口…