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

C#7 ref返回特性:内存留存的是类实例还是返回的引用属性?

C#7 ref返回特性:内存留存的是类实例还是仅引用的属性?

咱们直接把问题拆开来聊,先搞懂ref返回的本质,再解答你的疑问:

第一个问题:调用GetData()后内存里留存什么?

当你通过ref返回一个类(引用类型)实例的字段时,内存里会留存完整的MyDataStructure实例,而不是仅仅那个整数。

原因很直白:ref返回的是该int字段在内存中的直接地址,而这个地址属于整个MyDataStructure实例内存块的一部分。GC的回收逻辑是看有没有「根引用」关联到实例的任何部分——只要你还持有这个ref,就相当于给整个实例挂了根引用,GC就不会回收它,所以整个实例都会留在内存里。

第二个问题:为什么示例中的s无法被留存?

我猜你大概率写了类似这样的代码:

public ref int GetData()
{
    MyDataStructure s = new MyDataStructure(); // 局部变量s
    return ref s.Value;
}

这种情况编译器直接会报错,根本不让你通过,更别说留存s了。

核心原因是:s是方法内部的局部引用变量,它的作用域只限于这个方法。方法执行完毕后,栈上的s变量会被销毁,堆上的MyDataStructure实例此时没有任何合法的根引用——虽然你返回的ref指向它的字段,但这种指向局部实例字段的ref属于「悬空引用风险」,C#编译器为了避免你拿到指向已回收内存的无效引用,直接禁止了这种写法。

如果想让s的实例被留存,得让它的生命周期超出方法范围,比如把s设为类的成员变量,或者用ref/in修饰传入方法的参数(保证它的生命周期足够),举个合法的例子:

private MyDataStructure _s = new MyDataStructure(); // 类成员变量

public ref int GetData()
{
    return ref _s.Value;
}

这种情况下,只要你的类实例还活着,_s的实例就会被留存,返回的ref也能安全指向它的字段。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 09:01:09