首页 > 其他分享 >除了按值和引用,方法参数的第三种传递方式

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

时间:2024-08-23 08:57:41浏览次数:11  
标签:__ 按值 int 第三种 TypedReference value static 引用 passed

参数在方法种具有按“值(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;
}

标签:__,按值,int,第三种,TypedReference,value,static,引用,passed
From: https://www.cnblogs.com/artech/p/18374284/typed_reference

相关文章

  • 虚函数返回自己类型指针或引用,重写时返回类型可以不一样
    C++#include<functional>#include<iostream>#include<vector>#include<memory>#include<set>#include<map>#include<string>usingnamespacestd;namespace{/*C++类不能继承它自己*/classAnimal/*:public......
  • Latex引用两个文献——使用连字符
    Latex引用两个文献——使用连字符问题描述解决办法问题描述在一些国内期刊正文中引用参考文献时,如果是2个或者2个以上的连续数字时应该用连字符连起来,例如:“[1,3]”,“[4-5]”,但是使用常见的方法(\usepackage[numbers,sort&compress]{natbib})并不会对2个文献引用起作用......
  • 【C#】.NET报错:所生成项目的处理器框架“MSIL”与引用“xxx”的处理器架构“AMD64”不
    一、现象所生成项目的处理器架构“MSIL”与引用“System.Data.SQLite,Version=1.0.60.0,Culture=neutral,PublicKeyToken=db937bc2d44ff139,processorArchitecture=x86”的处理器架构“AMD64”不匹配。这种不匹配可能会导致运行时失败。请考虑通过配置管理器更改您的项目的......
  • Day03_0.1基础学习MATLAB学习小技巧总结(3)——矩阵的创建、引用和线性索引。
    利用暑假的时间把碎片化的MATLAB知识重新系统的学习一遍,为了在这个过程中加深印象,也为了能够有所足迹,我会把自己的学习总结发在专栏中,以便学习交流。素材来源“数学建模清风”特此说明:本博客的内容只在于总结在使用matlab中的一些小技巧,并非教程,若想系统的学习MATLAB,也可以......
  • Python之可变对象及其引用、深拷贝和浅拷贝
    可变对象及其引用深拷贝和浅拷贝可变对象及其引用Python中,变量名关联有值时才存在,如x=5变量名没有关联到特定的类型,类型有关联的对象觉得变量创建后即与特定的Python对象相关联Python维护命名空间,其中改变名与变量关联。这种联系,称为“引用”,也就是变量名引用对象......
  • 回归预测|基于北方苍鹰优化支持向量机的数据回归预测Matlab程序NGO-SVM 多特征输入单
    回归预测|基于北方苍鹰优化支持向量机的数据回归预测Matlab程序NGO-SVM多特征输入单输出高引用先用先创新文章目录前言回归预测|基于北方苍鹰优化支持向量机的数据回归预测Matlab程序NGO-SVM多特征输入单输出高引用先用先创新一、NGO-SVM模型1.北方苍鹰优化算......
  • C#不完全折腾:结构体,值类型,引用类型,泛型
    1.背景需要创建多个不同结构的结构体,依据输入的int数来选择并返回确定且唯一的结构体实例,并且实现把结构实例映射成一个字典(键值对)格式用来输出到richtextbox.2.结构体的初始化一个最基本的结构体格式如下://rwdim0publicstructrwdim0{publicushortblocktype......
  • 小小的引用计数,大大的性能考究
    本文基于Netty4.1.56.Final版本进行讨论在上篇文章《聊一聊Netty数据搬运工ByteBuf体系的设计与实现》中,笔者详细地为大家介绍了ByteBuf整个体系的设计,其中笔者觉得Netty对于引用计数的设计非常精彩,因此将这部分设计内容专门独立出来。Netty为ByteBuf引入了引......
  • 【Java】 方法引用与Lambda(快速上手)
    Java系列文章目录补充内容Windows通过SSH连接Linux第一章Linux基本命令的学习与Linux历史文章目录Java系列文章目录一、前言二、学习内容:三、问题描述四、解决方案:4.1方法引用五、总结:一、前言Calculator::plus看到::好奇有什么用二、学习内容:方法引用......
  • 【C++】看完就会--右值引用!!!
    右值引用一、什么是右值?什么是左值?二、右值引用三、右值引用的好处四、万能引用五、完美转发一、什么是右值?什么是左值?首先,当我们看到右值的时候,我们很自然的就会产生疑问?什么的右边呢?等号的右边吗?那么如果是按赋值=符号的右边来定义的话,那么,左值是不是就是=符号......