C#真正通过引用传递是通过引用传递吗?

Iva*_*gan 1 .net c#

void Method(ref int refArgument)
{
    refArgument = refArgument + 44;
}

int number = 1;
Method(ref number);
Console.WriteLine(number);
Run Code Online (Sandbox Code Playgroud)

在幕后,到底发生了什么?

它将内存地址传递给方法/功能,并更改存储在该内存地址中的值?

要么

它创建一个新的内存地址并将值存储在该新创建的地址中,并将变量(数字)指向新的内存地址吗?

哪一个

我的直觉是第一个,因为C#中的原始数据类型是struct,因此它们将始终按值传递

Max*_*Ast 5

如果我们看一下您的代码段的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         
Run Code Online (Sandbox Code Playgroud)

所以:

  1. ldind.i4 从提供的内存地址中加载值并将其压入堆栈
  2. ldc.i4.s 2C 将44加载到堆栈上
  3. add 您将堆栈的两个元素相加吗
  4. stind.i4 将加法结果存储回内存地址