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

C#主构造函数中仅用于初始化属性的传入变量是否会被保留?

C#主构造函数中仅用于初始化属性的传入变量是否会被保留?

我完全懂你的顾虑——尤其是在每秒处理上千个对象的场景下,哪怕一点点不必要的内存开销累积起来都可能出问题!先给你吃个定心丸:你用主构造函数传入的DeviceData对象,不会被DeviceDataStatus类持有,编译器能精准识别出你只用到了它的属性值,不会把这个引用留在类实例里,GC完全可以正常回收原DeviceData对象。

咱们来拆解一下你观察到的细节:

两种构造写法的实际效果完全等价

你写的主构造函数版本:

public class DeviceDataStatus(DeviceData data) {
    public uint DeviceId { get; } = data.DeviceId;
    public DeviceStatus Status { get; } = data.Status;
}

和传统构造函数版本:

public class DeviceDataStatus {
    public uint DeviceId { get; }
    public DeviceStatus Status { get; }

    public DeviceDataStatus(DeviceData data) {
        DeviceId = data.DeviceId;
        Status = data.Status;
    }
}

在编译后的IL层面几乎没有区别。编译器会把主构造函数里的属性初始化逻辑,直接转换成和传统构造函数一样的“构造函数内赋值”操作,不会额外保留data参数的引用。

关于Sharplab反编译结果的“奇怪”现象

你看到的反编译代码里,主构造函数版本的构造方法是空的,字段直接用data.DeviceId初始化——这其实是反编译工具的语法糖还原方式,不是实际运行的逻辑。真实的编译结果中,这些字段赋值是在构造函数内部执行的,而且不会将data参数存储为类的成员变量。你可以对比两者的IL代码(而不是反编译后的C#),会发现它们几乎完全一致。

结构体场景的额外验证

你提到如果传入的是大结构体会不会有双倍内存开销——放心,同样不会。主构造函数只会提取你需要的字段值赋值给新类的属性,不会复制整个结构体并保留它。和传统构造函数一样,只会占用必要的内存空间。

核心结论

不管用主构造函数还是传统构造函数,只要你没有在类的其他地方(比如其他方法、后续属性)引用data参数,编译器就不会保留这个引用。原DeviceData对象在构造完DeviceDataStatus后,只要没有其他地方引用它,就会被GC正常回收,不会造成内存开销。

所以你完全可以放心使用主构造函数的简洁写法,既保持了代码整洁,又不会有内存方面的顾虑。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 07:20:28