ref详解(C#)
本质上来说 ref 的就是把 C/C++ 指针的那一套又拿回来了,而且还封装成一套自己的玩法。
我想设计者的初心把 ref 的功能限制得死死的,可能也考虑到 C# 是一门面向业务开发的语言,讲究的是做项目快狠准,性能反而不是第一要素,这个时候的 ref 很简单,看一下代码:
class Program
{static void Main(string[] args){long price = 0;GetPrice(ref price);Console.WriteLine($"output: price={price}");}public static void GetPrice(ref long price){price = 10;} }
// output: price=10
我相信大家都知道,方法参数中ref long price拿的是栈中的地址,对栈地址上的值进行修改,地址上的变量会被修改,和引用类型原理一致,接下来咋就从汇编的角度去看看。
D:\net5\ConsoleApp4\ConsoleApp3\Program.cs @ 16:026b048e 8d4declea ecx,[ebp-14h]026b0491 ff15a0ebc800 call dword ptr ds:[0C8EBA0h] (ConsoleApp3.Program.GetPrice(Int64 ByRef), mdToken:06000002)026b0497 90 nop0:000> bp 026b04910:000> gBreakpoint 1 hitChangeEngineStateeax=00000000 ebx=0057f354 ecx=0057f2d4 edx=783aaa50 esi=02979e7c edi=0057f2dceip=026b0491 esp=0057f2c4 ebp=0057f2e8 iopl=0 nv up ei pl zr na pe nccs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
026b0491 ff15a0ebc800 call dword ptr ds:[0C8EBA0h] ds:002b:00c8eba0=00c2be10
从汇编的lea ecx,[ebp-14h]就能看到,将ebp-14这个单元的内存地址给了 ecx,这个 ecx 也就是作为参数传递给了Price方法,后续的赋值将会影响这个栈位置上的内容。
方法返回值上的 ref
这就有意思了,进入的时候传地址,回来的时候也想传地址,很显然方法线程栈上的 值类型 是传不出去的,毕竟方法返回后,esp,ebp 所控制的方法栈帧空间是要销毁的,所以只能是堆上对象才能实现。
为了方便理解,看如下代码:
class Program
{static void Main(string[] args){ref long price = ref TaskClass.GetCurrentPrice();price = 12;Console.WriteLine($"output: price={price}");}public static ref long GetCurrentPrice(){long[] nums = { 10, 20, 30 };return ref nums[1];}}
// output: price=12
可以看到当前的price=12,同时nums这个数组也被修改了,可以用 windbg 验证一下。
0:000> !dumpheap -type System.Int64[]Address MT Size027ca7b0 04c39d00 36Statistics:MT Count TotalSize Class Name04c39d00 136 System.Int64[]Total 1 objects0:000> dq 027ca7b0 L4027ca7b0 00000003`04c39d00 00000000`0000000a027ca7c0 00000000`0000000c 00000000`0000001e
可以看到上面的000000000000000c被修改成price=12,这时候有人就不爽了,我不希望外面的代码能修改 price 内容,那怎么办呢? 还得在ref后面加上readonly,改造后如下:
到此时写法就有点疯狂了,对 C# 开发者来说很难理解,对熟悉 C/C++ 指针的朋友来说又很不习惯,太纠结了,下面是一段翻译过来的C/C++指针代码。
const long long* getcurrentprice();int main()
{int i = 0;const long long* price = getcurrentprice();price = 12;printf("num=%d, price=%d \n", i, *price);}const long long* getcurrentprice() {long long* num = new long long[3]{ 10,20,30 };return num + 1;
}
对 ref 变量的 in 操作
这又是一套 C/C++ 的玩法,有时候不希望某一个方法对 ref 变量进行修改,注意:是不希望某一个方法进行修改,其他方法是可以的,那这个怎么实现呢?这就需要在入参上加in前缀,把代码修改一下。
class Program
{static void Main(string[] args){ref long price = ref GetCurrentPrice();ModifyPrice(in price);Console.WriteLine($"output: price={price}");}public static ref long GetCurrentPrice(){long[] nums = { 10, 20, 30 };return ref nums[1];}public static void ModifyPrice(in long price){price = 12;Console.WriteLine(price);}
}
可以看到,这时候报错了,如果换成 C++ 就很简单了,只需要在参数上把 in 改成 const 即可。
void modifyprice(const long long* price) {*price = 12;printf("%d", *price);
}
总的来说,ref 这一套玩法太另类了,按实际需求使用,不太会去考虑性能方面的问题。
相关文章:

ref详解(C#)
本质上来说 ref 的就是把 C/C 指针的那一套又拿回来了,而且还封装成一套自己的玩法。 我想设计者的初心把 ref 的功能限制得死死的,可能也考虑到 C# 是一门面向业务开发的语言,讲究的是做项目快狠准,性能反而不是第一要素&#x…...

运维高级-day01
shell回顾 1、快速生成版权控制信息,具体的内容自己替换 [root scripts]# cat ~/.vimrc autocmd BufNewFile *.py,*.cc,*.sh,*.java exec ":call SetTitle()" func SetTitle() if expand("%:e") sh call setline(1,"#!/bin/bash")…...

含分布式电源的配电网可靠性评估matlab程序
微❤关注“电气仔推送”获得资料(专享优惠) 参考文献: 基于仿射最小路法的含分布式电源配电网可靠性分析——熊小萍 主要内容: 通过概率模型和时序模型分别进行建模,实现基于概率模型最小路法的含分布式电源配电网…...
k8s docker总结特殊点
k8s docker总结特殊点 前言一、docker 的驱动。1、cgroup:(Control Groups)2、日志驱动(log driver)3、存储驱动4、网络驱动: 二、k8s中网络插件(常用calico,次flannel)**Flannel:**…...

区块链技术与应用 【全国职业院校技能大赛国赛题目解析】第四套区块链应用后端开发
第四套区块链应用后端开发 环境 : ubuntu20 fisco : 2.8.0 springboot 2.1.1 fisco-java-sdk: 2.7.2 maven 3.8.8 前言 这套后端样题,只涉及调用fisco的系统接口,不涉及此食品溯源项目的业务接口,所以我就直接生成一个springboot项目进行完成此题目。 请提前准备好一…...

《向量数据库指南》——向量数据库Milvus Cloud搭建Excel公式编辑器助手
引言 在日常工作中,Excel是我们经常使用的办公工具,而熟练应用Excel公式对于提高工作效率非常重要。然而,有时候我们会遇到一些复杂的需求,需要用到较为专业的Excel公式,而这正是Excel公式编辑器助手的用武之地。本文将介绍如何利用向量数据库Milvus Cloud搭建GPT大模型和…...

qgis添加arcgis的FeatureServer
左侧浏览器-ArcGIS要素服务器-新建连接 http://sampleserver6.arcgisonline.com/arcgis/rest/services/ 展开-双击即可...
java进阶---多态
多态的概述 什么是多态 同一个对象,在不同时刻表现出来的不同形态 多态的前提 要有继承或实现关系要有方法的重写要有父类引用指向子类对象 多态的具体实现 对象的多态是多态的核心和重点 规则: 一个对象的编译类型与运行类型可以不一致编译类型在定义对象时,就确定了,…...
常用脚本-持续更新(文件重命名、视频抽帧、拆帧、删除冗余文件、yolo2xml、转换图片格式、修改xml)
所有代码位置:Learning-Notebook-Codes/Python/常用脚本 1. 文件重命名 脚本路径:codes/files_rename.py脚本说明:可以自动重命名某个文件夹下指定类型的文件。 修改前文件名称: img1.jpg修改后文件名称: Le0v1n-20231123-X-0001.jpg imp…...

百度文心一言(千帆大模型)聊天API使用指导
开篇不得不吐槽下百度,百度智能云平台首页跳转千帆大模型平台的按钮太多了,不同按钮跳转不同的子页面,不熟悉的,能把人找懵。入口太多,就导致用户不知道从何开始。本文就从一个前端开发人员的角度,教大家快…...

C++知识点总结(7):玩转高精度除法
一、复习高低精度 一个数分为两种类型: 1. 高精度数,即一个长度特别长的数,使用 long long 也无法存储的一类数字。 2. 低精度数,即一个普通的数,可以使用 long long 来存储。 由于高精度除法比较简单,…...
LeetCode算法题解(动态规划,背包问题)|LeetCode1049. 最后一块石头的重量 II、LeetCode494. 目标和
一、LeetCode1049. 最后一块石头的重量 II 题目链接:1049. 最后一块石头的重量 II 题目描述: 有一堆石头,用整数数组 stones 表示。其中 stones[i] 表示第 i 块石头的重量。 每一回合,从中选出任意两块石头,然后将…...

使用Pytorch从零开始构建LSTM
长短期记忆(LSTM)网络已被广泛用于解决各种顺序任务。让我们了解这些网络如何工作以及如何实施它们。 就像我们一样,循环神经网络(RNN)也可能很健忘。这种与短期记忆的斗争导致 RNN 在大多数任务中失去有效性。不过&a…...

qRT-PCR相对定量计算详解qPCR相对定量计算方式——2^-(∆∆Ct) deta t
做完转录组分析之后,一般都要求做qRT-PCR来验证二代测序得到的转录本表达是否可靠。荧光定量PCR是一种相对表达定量的方法,他的计算方法有很多,常用的相对定量数据分析方法有双标曲线法,ΔCt法,2^-ΔΔCt法(Livak法)&a…...
BART non-Cartesian 重建:并行成像 压缩感知
本文主要使用并行成像和压缩感知方法实现non-Cartesian MRI 数据的重建。 目录 1 自定义MRI kspace trajectory 2 自定义该 trajectory下的多通道MRI数据 3 使用NUFFT 直接做欠采样数据的重建...

UDP客户端使用connect与UDP服务器使用send函数和recv函数收发数据
服务器代码编译运行 服务器udpconnectToServer.c的代码如下: #include<stdio.h> #include<stdlib.h> #include<string.h> #include<unistd.h> #include<arpa/inet.h> #include<sys/socket.h> #include<errno.h> #inclu…...
SLAM ORB-SLAM2(9)闭环检测器
SLAM ORB-SLAM2(9)闭环检测器 1. LoopClosing2. 成员变量2.1. 系统成员变量2.2. 关键帧2.3. 共视关系2.4. 闭环检测2.5. 全局 BA(光束法平差)2.6. 其他操作3. 成员函数3.1. 构造函数3.2. 主要函数3.3. 更新操作3.4. 标识设置和查询接口1. LoopClosing 在《SLAM ORB-SLAM2(…...
目标检测YOLO系列从入门到精通技术详解100篇-【目标检测】SLAM(基础篇)(二)
目录 知识储备 概率论基础 边缘概率 联合概率和独立 独立与条件独立...

TikTok 将开源“云中和”边缘加速器
“从某种意义上说,我们正在努力破解云的骨干网,以造福于我们,”TikTok产品管理基础设施经理Vikram Siwach指出,他解释了该公司即将开源的“全球服务加速器”的好处,这是一个可编程的边缘平台,可将应用程序需…...

【通讯协议】REST API vs GraphQL
在API设计方面,REST和GraphQL各有缺点。下图显示了 REST 和 GraphQL 之间的快速比较。 REST 使用标准 HTTP 方法(如 GET、POST、PUT、DELETE)进行 CRUD 操作。当您需要在单独的服务/应用程序之间提供简单、统一的接口时,效果很好…...

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型
摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...

Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...

简易版抽奖活动的设计技术方案
1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...

高危文件识别的常用算法:原理、应用与企业场景
高危文件识别的常用算法:原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件,如包含恶意代码、敏感数据或欺诈内容的文档,在企业协同办公环境中(如Teams、Google Workspace)尤为重要。结合大模型技术&…...

C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...
Matlab | matlab常用命令总结
常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...

ardupilot 开发环境eclipse 中import 缺少C++
目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...
【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)
1.获取 authorizationCode: 2.利用 authorizationCode 获取 accessToken:文档中心 3.获取手机:文档中心 4.获取昵称头像:文档中心 首先创建 request 若要获取手机号,scope必填 phone,permissions 必填 …...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...