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

C#引用类型按ref传递后赋值新对象,堆内存地址是否改变?

C#中ref传递引用类型时对象地址变化的疑问解答

你的理解是正确的:当引用类型通过ref关键字传递给方法时,在方法内给参数赋值新对象,主函数中的原变量(比如你的t1)确实会指向新的对象,它的引用地址应该发生变化。

你看到地址保持不变,大概率是验证过程中出现了误解或者调试工具的显示问题。我们结合你的代码来拆解整个过程:

  1. 初始状态:Test t1 = new Test() { a = 10 }; 此时t1指向内存中一个新创建的Test对象,假设这个对象的地址是地址A。
  2. 传递参数:调用GetCallByRefForObj(ref t1)时,ref关键字让方法内的参数x成为t1变量本身的引用——也就是说,x和t1是同一个变量的不同名字,它们指向同一个对象(地址A)。
  3. 赋值新对象:在方法内执行x = new Test() { a = 10 };,这会创建一个新的Test对象(地址B),并让x(也就是t1)指向这个新对象。此时主函数中的t1已经不再指向原来的地址A,而是地址B。

如果想准确验证地址变化,可以在代码中添加打印对象地址的逻辑,比如:

using System.Runtime.InteropServices;

class Test
{
    public int a { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        Test t1 = new Test() { a = 10 };
        Console.WriteLine($"调用方法前,t1指向的对象地址: {GetObjectAddress(t1)}");
        GetCallByRefForObj(ref t1);
        Console.WriteLine($"调用方法后,t1指向的对象地址: {GetObjectAddress(t1)}");
    }

    public static void GetCallByRefForObj(ref Test x)
    {
        x = new Test() { a = 10 };
    }

    private static long GetObjectAddress(object obj)
    {
        return Marshal.GetIUnknownForObject(obj).ToInt64();
    }
}

运行这段代码,你会看到前后打印的地址完全不同,这就证明t1的引用确实指向了新的对象。

你之前的验证结果(地址不变),可能是因为调试时在赋值新对象前查看了t1的地址,之后没有重新查看;或者调试工具显示的是原对象的地址,而非t1当前指向的地址。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 14:23:25