C#结构体中包含reference类型字段是否属于正确的使用方式?
结构体包含引用类型字段的用法说明
语法层面是完全合法的
C# 官方并没有禁止结构体中定义引用类型的字段,你提供的代码可以正常编译运行,本质上结构体中存储的是引用类型的内存地址(即引用本身),而非引用指向的对象实例,引用本身属于值类型,会直接存储在结构体的内存空间中。
示例代码如下:
public class ClassA { //... } public class ClassB { //... } public struct StructAB { public ClassA a; public ClassB b; public StructAB(ClassA ca,ClassB cb) { this.a = ca; this.b = cb; } }
设计层面不推荐随意使用
绝大多数场景下不建议在结构体中定义可变的引用类型字段,主要有以下几个易踩的问题:
- 违背值类型的行为预期:结构体属于值类型,赋值、传参时会默认做逐位拷贝,拷贝后两个结构体持有的引用指向同一个对象,修改其中一个结构体引用成员的内部属性,会同步影响另一个结构体的对应成员,和大众认知里「修改值类型副本不影响原值」的预期不符,极易产生隐藏Bug。
- 破坏结构体的不可变性:行业通用的最佳实践是把结构体设计为不可变类型,如果你在结构体中放入可变的引用类型,就算结构体本身声明为
readonly,你依然可以修改引用指向对象的内部属性,彻底破坏结构体的不可变特性。 - 抵消结构体的性能优势:很多场景用结构体是为了减少GC堆分配、降低GC压力,但结构体中存储引用类型后,GC需要遍历扫描所有结构体实例持有的引用,反而会增加GC的开销,完全抵消结构体的性能优势。
符合以下场景可以有限使用
如果你能明确规避上述风险,也可以在结构体中使用引用类型字段,常见的合法场景:
- 引用类型本身是不可变的:最典型的就是
string,我们日常用到的很多结构体都包含string类型字段,因为不可变的引用类型不会出现修改副本影响原值的问题,属于安全用法。 - 仅限内部小范围使用:结构体作为内部临时数据结构,仅在小范围可控的代码中传递,不会对外暴露,且你能保证不会出现非预期的结构体拷贝操作。
内容的提问来源于stack exchange,提问作者Circle
相关产品推荐
相关产品推荐

