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

2024-08-24 07:28

本文主要是介绍除了按值和引用,方法参数的第三种传递方式,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、官方描述

三种参数传递方式并非我们杜撰出来的,而是写在.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;
}

文章转载自:Artech

原文链接:https://www.cnblogs.com/artech/p/18374284/typed_reference

体验地址:引迈 - JNPF快速开发平台_低代码开发平台_零代码开发平台_流程设计器_表单引擎_工作流引擎_软件架构

这篇关于除了按值和引用,方法参数的第三种传递方式的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1101834

相关文章

虚拟机与物理机的文件共享方式

《虚拟机与物理机的文件共享方式》文章介绍了如何在KaliLinux虚拟机中实现物理机文件夹的直接挂载,以便在虚拟机中方便地读取和使用物理机上的文件,通过设置和配置,可以实现临时挂载和永久挂载,并提供... 目录虚拟机与物理机的文件共享1 虚拟机设置2 验证Kali下分享文件夹功能是否启用3 创建挂载目录4

linux报错INFO:task xxxxxx:634 blocked for more than 120 seconds.三种解决方式

《linux报错INFO:taskxxxxxx:634blockedformorethan120seconds.三种解决方式》文章描述了一个Linux最小系统运行时出现的“hung_ta... 目录1.问题描述2.解决办法2.1 缩小文件系统缓存大小2.2 修改系统IO调度策略2.3 取消120秒时间限制3

Linux alias的三种使用场景方式

《Linuxalias的三种使用场景方式》文章介绍了Linux中`alias`命令的三种使用场景:临时别名、用户级别别名和系统级别别名,临时别名仅在当前终端有效,用户级别别名在当前用户下所有终端有效... 目录linux alias三种使用场景一次性适用于当前用户全局生效,所有用户都可调用删除总结Linux

Oracle查询优化之高效实现仅查询前10条记录的方法与实践

《Oracle查询优化之高效实现仅查询前10条记录的方法与实践》:本文主要介绍Oracle查询优化之高效实现仅查询前10条记录的相关资料,包括使用ROWNUM、ROW_NUMBER()函数、FET... 目录1. 使用 ROWNUM 查询2. 使用 ROW_NUMBER() 函数3. 使用 FETCH FI

Git中恢复已删除分支的几种方法

《Git中恢复已删除分支的几种方法》:本文主要介绍在Git中恢复已删除分支的几种方法,包括查找提交记录、恢复分支、推送恢复的分支等步骤,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录1. 恢复本地删除的分支场景方法2. 恢复远程删除的分支场景方法3. 恢复未推送的本地删除分支场景方法4. 恢复

Python将大量遥感数据的值缩放指定倍数的方法(推荐)

《Python将大量遥感数据的值缩放指定倍数的方法(推荐)》本文介绍基于Python中的gdal模块,批量读取大量多波段遥感影像文件,分别对各波段数据加以数值处理,并将所得处理后数据保存为新的遥感影像... 本文介绍基于python中的gdal模块,批量读取大量多波段遥感影像文件,分别对各波段数据加以数值处

Window Server2016加入AD域的方法步骤

《WindowServer2016加入AD域的方法步骤》:本文主要介绍WindowServer2016加入AD域的方法步骤,包括配置DNS、检测ping通、更改计算机域、输入账号密码、重启服务... 目录一、 准备条件二、配置ServerB加入ServerA的AD域(test.ly)三、查看加入AD域后的变

Window Server2016 AD域的创建的方法步骤

《WindowServer2016AD域的创建的方法步骤》本文主要介绍了WindowServer2016AD域的创建的方法步骤,文中通过图文介绍的非常详细,对大家的学习或者工作具有一定的参考学习价... 目录一、准备条件二、在ServerA服务器中常见AD域管理器:三、创建AD域,域地址为“test.ly”

NFS实现多服务器文件的共享的方法步骤

《NFS实现多服务器文件的共享的方法步骤》NFS允许网络中的计算机之间共享资源,客户端可以透明地读写远端NFS服务器上的文件,本文就来介绍一下NFS实现多服务器文件的共享的方法步骤,感兴趣的可以了解一... 目录一、简介二、部署1、准备1、服务端和客户端:安装nfs-utils2、服务端:创建共享目录3、服

MySQL中时区参数time_zone解读

《MySQL中时区参数time_zone解读》MySQL时区参数time_zone用于控制系统函数和字段的DEFAULTCURRENT_TIMESTAMP属性,修改时区可能会影响timestamp类型... 目录前言1.时区参数影响2.如何设置3.字段类型选择总结前言mysql 时区参数 time_zon