You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#引用传参时栈推送内容与ref返回值问题咨询

C#中引用传递时栈上的内容解析

先给你理清楚C#里值传递和ref传递的本质,结合你给的代码逐个拆解:

1. 普通传递引用类型(比如代码中的e1)

当你把e1作为参数传给method时,栈上推送的是**e1变量存储的引用值**——说白了就是托管堆上那个em实例的内存地址(32位系统是4字节,64位是8字节)。

  • 这时候method里的参数c是这个引用的副本,你修改c.i会影响堆上的原对象(因为副本和原引用指向同一个堆实例),但如果给c赋值new em(),只会改变c这个副本的引用值,完全不会影响Main里的e1变量。

2. ref传递引用类型(比如代码中的ref e2)

这时候栈上推送的是**Main方法栈帧里e2变量本身的内存地址**——也就是栈上存储e2那个引用的位置的地址。

  • method里的参数d相当于e2变量的别名,操作d就等于直接操作Main里的e2:
    • 修改d.i:先通过d找到e2的引用值,再指向堆上的em实例,最终修改堆对象的字段,和普通传递的效果一致;
    • 给d赋值new em():直接把新的引用值写到e2在栈上的位置,所以Main里的e2会直接指向新的堆实例,这是普通传递做不到的。

3. ref返回对象时传递的内容

当你用ref返回一个对象(或者对象的字段)时,返回的是目标变量的内存地址:

  • 如果返回的是ref d(也就是ref e2),那返回的就是e2变量在栈上的地址,调用方用ref em result = ref p.method(...)接收后,修改result就等于修改e2;
  • 如果返回的是ref d.i,那返回的是堆上em实例中i字段的地址,调用方修改result会直接改变堆对象的i值,不需要通过引用间接访问。

举个简单的代码片段辅助理解:

public ref em method(ref em d)
{
    // 返回e2变量的地址
    return ref d;
}

// 在Main里调用
ref em result = ref p.method(ref e2);
result = new em(); // 这会直接修改Main里的e2

内容的提问来源于stack exchange,提问作者123

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 09:00:35