C# 只读成员(readonly members) - 在结构体中保证不变性

来源:这里教程网 时间:2026-02-21 17:39:18 作者:

在 C# 中,readonly 成员(C# 7.2 引入)是结构体(

struct
)实现真正不变性的关键机制。它让编译器强制保证:只要一个结构体实例被标记为
readonly
(比如作为只读字段、
in
参数或
readonly
局部变量),那么调用其
readonly
成员时,不会意外修改其状态。

为什么结构体需要 readonly 成员?

结构体是值类型,按值传递。但若结构体包含可变字段,又没加约束,很容易在看似“只读”的上下文中被意外修改——比如调用一个非

readonly
的方法,该方法内部却修改了字段。编译器无法阻止这种行为,除非你显式声明成员为
readonly

没有

readonly
成员时:

即使结构体变量被声明为
readonly
,仍可调用非
readonly
方法;
这些方法可能悄悄改写字段,破坏语义上的“只读”承诺; 尤其在
in
参数场景下,容易引发难以调试的副作用。

如何正确声明 readonly 成员?

在方法、属性访问器、索引器、运算符等成员上添加

readonly
修饰符:

方法:在返回类型前加
readonly
,如
public readonly int GetValue() => _value;
属性 getter:在
get
前加
readonly
,如
public readonly int Value => _value;
整个属性设为
readonly
:表示 get/set 都不能修改状态(set 必须也是
readonly
,且通常只用于初始化逻辑);
readonly
成员内不可调用非
readonly
成员,也不可直接赋值给任何字段(包括
this
字段)。

readonly 成员与 readonly struct 的区别

readonly struct
(C# 7.2+)是更严格的契约:它要求结构体所有实例字段必须是
readonly
,且所有成员默认隐式为
readonly
(除非显式去掉)。而普通结构体中使用
readonly
成员,是“按需加锁”,更灵活:

允许结构体保留可变字段(如用于内部缓存),但把公共 API 设为
readonly
适合渐进式改造旧结构体,无需一次性冻结所有字段; 编译器对
readonly struct
有额外优化(如允许安全地按
in
传递)。

实际使用建议

要真正发挥 readonly 成员的作用,需配合使用场景:

把结构体字段尽量设为
readonly
,从源头减少可变性;
所有公开的、不改变状态的方法/属性,一律标注
readonly
在参数中优先用
in
替代
ref
或值传递,此时编译器会强制只调用
readonly
成员;
避免在
readonly
成员里调用非
readonly
方法(编译器报错),也别用
Unsafe.AsRef
等绕过检查——那等于放弃保障。

基本上就这些。readonly 成员不是语法糖,而是编译器帮你守住结构体不变性的第一道防线。

相关推荐