c# - C# 通过 ref 在引擎盖下传递它真的是通过引用传递吗?
问题描述
void Method(ref int refArgument)
{
refArgument = refArgument + 44;
}
int number = 1;
Method(ref number);
Console.WriteLine(number);
在引擎盖下,到底发生了什么?
它将内存地址传递给方法/函数并更改存储在该内存地址中的值?
或者
它创建一个新的内存地址并将值存储在新创建的地址中,并将变量(数字)指向新的内存地址?
哪个是哪个?
我的预感是第一个,因为 C# 中的原始数据类型是结构,因此它们总是按值传递
解决方案
如果我们看一下您的代码段的 IL 代码:
IL_0000: nop
IL_0001: nop
IL_0002: ldc.i4.1
IL_0003: stloc.0 // number
// Loads the address of the local variable at a specific index onto the evaluation stack, short form. see: https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.ldloca_s?view=netframework-4.7.2
IL_0004: ldloca.s 00 // number
IL_0006: call g__Method|0_0
IL_000B: nop
IL_000C: ldloc.0 // number
IL_000D: call System.Console.WriteLine
IL_0012: nop
IL_0013: ret
g__Method|0_0:
IL_0000: nop
// ldarg.0 called twice: 1. for ldind.i4 and 2. to store the result back to the memory location in stind.i4
IL_0001: ldarg.0
IL_0002: ldarg.0
// Loads a value of type int32 as an int32 onto the evaluation stack indirectly. see: https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.ldind_i4?view=netframework-4.7.2
// --> It used the passed intptr
IL_0003: ldind.i4
IL_0004: ldc.i4.s 2C
IL_0006: add
// Stores a value of type int32 at a supplied address. see: https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.stind_i4?view=netframework-4.7.2
IL_0007: stind.i4
IL_0008: ret
所以:
ldind.i4
从提供的内存地址加载值并将其推入堆栈ldc.i4.s 2C
将 44 加载到堆栈上add
您是否添加了堆栈的两个元素stind.i4
将加法的结果存储回内存地址
推荐阅读
- c# - C# 方法不遵循顺序
- javascript - 为许多视频初始化时如何获取 Plyr 当前实例
- android - 如何暂停 for 循环的完成,直到满足 AudioIsCompletedCondition
- ios - 如何在 iOS 上的 mapView 上添加固定栏
- php - Laravel 迁移名称太长
- javascript - 从 Electron 中的最小化恢复后,我们可以强制 mainWindow 专注于一些 DOM 吗?
- spring-webflow-2 - spring webflow的on-start元素什么时候执行?
- javascript - 如何全选并重置传单中的所有选定标记
- typeorm - 如何使用 TypeORM 查询多对多关系
- ios - 如何更改对象的位置 Swift SceneKit