除了按值和引用,方法参数的第三种传递方式

参数在方法种具有按“值(by value)”和“引用(by ref)”两种传递方式,这是每个.NET程序员深入骨髓得基本概念。但是我若告诉你,.NET规定的参数传递形式其实是三种,会不会颠覆你的认知。

一、官方描述
二、TypedReference结构体
三、三个特殊的方法
四、三种参数传递方式

一、官方描述

三种参数传递方式并非我们杜撰出来的,而是写在.NET最核心的规范文档ECMA-355中(I.12.4.1.5),原文如下:

The CLI supports three kinds of parameter passing, all indicated in metadata as part of the signature of the method. Each parameter to a method has its own passing convention (e.g., the first parameter can be passed by-value while all others are passed byref). Parameters shall be passed in one of the following ways (see detailed descriptions below):

  • By-value – where the value of an object is passed from the caller to the callee.
  • By-reference – where the address of the data is passed from the caller to the callee, and the type of the parameter is therefore a managed or unmanaged pointer.
  • Typed reference – where a runtime representation of the data type is passed along with the address of the data, and the type of the parameter is therefore one specially supplied for this purpose.

It is the responsibility of the CIL generator to follow these conventions. Verification checks that the types of parameters match the types of values passed, but is otherwise unaware of the details of the calling convention.

三种参数传递方式如下:

  • By-value:传递参数的值或者拷贝。这里所谓的值分两种情况,对于值类型,变量的值就是承载目标值的字节,比如参数类型是一个我们自定义的结构体,那么传递的是承载这个结构体内容的所有字节;对于引用类型,变量的值是目标对象的内存地址,所以传递的这个地址(4/8字节)的拷贝;
  • By-Reference: 传递的是变量所在的位置(Location),可能是变量在堆栈上的内存地址,或者数组元素在堆上的内存地址。所以方法不仅仅可以从这个地址读取原始参数当前的值,还可以通过填充字节到此位置改变原始的值。对于值类型,被调用方法可以将原始的值“就地”变成一个新的值;对于引用类型,方法则会原来的引用指向一个新的对象。
  • Typed reference:可以认为强类型的引用,在By-Reference基础上还传递参数的类型;

二、TypedReference

基于Typed reference的传递时通过如果这个TypedReference结构体实现的,从其定义可以看出它通过字段_value保持值得引用,并利用_type确定其类型。它定义了一系列静态方法完成一些基于TypedReference得基本操作,比如创建一个TypedReference对象,将一个TypedReference对象转换成Object,获取TypedReference对象得目标类型等;

public struct TypedReference
{private readonly ref byte _value;private readonly IntPtr _type;public unsafe static object ToObject(TypedReference value);public unsafe static TypedReference MakeTypedReference(object target, FieldInfo[] flds);public static Type GetTargetType(TypedReference value);public static RuntimeTypeHandle TargetTypeToken(TypedReference value);public static void SetTypedReference(TypedReference target, object value);
}

三、三个特殊的方法

TypedReference还涉及三个如下三个特殊方法或者函数,可能很多开源人员都没有见过:

  • __makeref:创建一个新的TypedReference对象;
  • __reftype:获取引用的目标类型;
  • __refvalue:获取和设置引用的值;

四、三种参数传递方式

我们通过如下这个简单的例子来演示上述的三种参数传递方式,它们分别体现在三个对应的方法上。模拟按照Typed reference进行参数传递的PassByTypedReference方法将参数类型定义为TypedReference,它通过断言检验传递参数的类型(通过调用__reftype方法获取),并通过调用__refvalue修改参数的值。

PassByValue(value);
Debug.Assert(value == int.MinValue);PassByReference(ref value);
Debug.Assert(value == int.MaxValue);value = int.MinValue;
PassByTypedReference(__makeref(value));
Debug.Assert(value == int.MaxValue);static void PassByValue(int v) => v = int.MaxValue;
static void PassByReference(ref int v) => v = int.MaxValue;
static void PassByTypedReference(TypedReference v)
{Debug.Assert(__reftype(v) == typeof(int));__refvalue(v, int) = int.MaxValue;
}

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

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

相关文章

强!34.1K star! 再见Postman,新一代API测试利器,功能强大、颜值爆表!

1、引言 在当今的互联网时代,API(应用程序编程接口)已经成为连接不同软件系统的桥梁。作为一名开发者,掌握API测试技能至关重要。市面上的API测试工具琳琅满目,今天我们要介绍的是一款开源、跨平台的API测试工具——Insomnia。 2、Insomnia介绍 Insomnia是一款功能丰富、易…

Modbus初学者教程,第五章:Modbus 中的功能码和异常码

第五章:Modbus 中的功能码和异常码平时调试Modbus设备,或者学习Modbus协议,推荐一款Modbus主从站模拟器: 主站下载地址:Modbus从站模拟器 从站下载地址:Modbus主站模拟器可视化 Modbus 设备中的数据 Modbus 从设备可以想象为具有一个内部电子表格,其中填满了数字。Modbu…

袋鼠

先转化一下题意:求有多少个1~n的排列p能够满足 \(\forall i \in (1,n)\) ,使 $ p_{i} $ 左右两边的数同时小于或者大于 \(p_{i}\) ,并且\(p_{1}=s,p_{n}=t\) 。 比较明显的预设型DP(连转化题意我都做不到,悲),先正常来分析一下,我们填数从小往大枚举,如果我们填入一个数,…

JetBrains Writerside 2024.2 (macOS, Linux, Windows) - 编写、测试、构建和发布最佳教程

JetBrains Writerside 2024.2 (macOS, Linux, Windows) - 编写、测试、构建和发布最佳教程JetBrains Writerside 2024.2 (macOS, Linux, Windows) - 编写、测试、构建和发布最佳教程 JetBrains 跨平台开发者工具 请访问原文链接:https://sysin.org/blog/jetbrains-writerside/…

Citrix ADC Release 13.1 Build 54.29 (nCore, VPX, SDX, CPX, BLX) - 混合多云应用交付控制器

Citrix ADC Release 13.1 Build 54.29 (nCore, VPX, SDX, CPX, BLX) - 混合多云应用交付控制器Citrix ADC Release 13.1 Build 54.29 (nCore, VPX, SDX, CPX, BLX) - 混合多云应用交付控制器 Citrix ADC - 混合多云应用交付控制器 请访问原文链接:https://sysin.org/blog/citr…

Metasploit Pro 4.22.3-2024081901 (Linux, Windows) - 专业渗透测试框架

Metasploit Pro 4.22.3-2024081901 (Linux, Windows) - 专业渗透测试框架Metasploit Pro 4.22.3-2024081901 (Linux, Windows) - 专业渗透测试框架 Rapid7 Penetration testing, release Aug 19, 2024 请访问原文链接:https://sysin.org/blog/metasploit-pro-4/,查看最新版。…

dotnet X11 栈空间被回收导致调用 XPutShmImage 闪退

本文记录在使用 X11 过程中的问题,由于不正确使用导致栈空间被回收,从而在调用 XPutShmImage 时让应用闪退,此问题本质上讲只和 X11 的设计有一分钱关系,更多的问题在于我的写法上在 上一篇博客 里,介绍了使用 MIT-SHM 共享内存推送图片,详细请看:dotnet X11 简单使用 M…

Avalonia 11.1 已知问题 IterationCount 为 Infinite 的动画播放出现异常

如果在 Avalonia 后台代码播放一个动画,这个动画的 Animation 的 IterationCount 被设置为 Infinite 那么将在播放的时候抛出 InvalidOperationException 异常本文所使用的 Avalonia 为 11.1.0 版本,由于 Avalonia 行为和 API 变动较多,如大家使用其他版本还请重新测试 如以…

11 Large Companies That Use Java

https://terenbro.com/blog/11-large-companies-that-use-javaWhat is Java? Why do Companies Use Java? 11 Companies That Use Java Overview List of Companies That Use Java Consider Terenbro as Your Trusted Partner Final ThoughtsTOP-5 PostsPopular Java Use Cas…

mysql全片篇

零,快速总结篇# 1)、查询所有数据库 show databases ; # 2)、查询当前数据库 select database() ; # 3)、创建数据库 create database [ if not exists ] 数据库名 [ default charset 字符集 ] [ collate 排序规则 ] ; # 4)、删除数据库 drop database [ if exists ] 数据库名…

最简单100%解决pip 不是内部或外部命令,也不是可运行的程序 或批处理文件

相信你看了不少教程还是没有解决pip的问题 最关键的问题还是在于没有找到正确的路径。 解决办法: 在cmd中输入python -m pip install --upgrade pip, 它会告诉你 WARNING: Ignoring invalid distribution -ip (d:\python3.9\lib\site-packages)Requirement already satisfie…