如何修改readonly变量的值?Account类CashIn方法更新balance方案
能否在CashIn方法中更新readonly的balance字段?
好问题!先直接给你结论:常规情况下,你没法在CashIn方法里直接更新readonly修饰的balance字段——这是C#里readonly修饰符的核心规则决定的。
为什么不行?
readonly字段的设计目的就是保证字段的值只能在两个时机被赋值:
- 字段本身初始化的时候(比如
public readonly decimal balance = 0;) - 类的构造函数里(包括实例构造和静态构造,如果是静态readonly字段)
一旦对象创建完成,readonly字段的值就被“锁定”了,普通成员方法(比如你的CashIn)里直接赋值会触发编译错误——这是C#编译器强制的安全检查,就是为了确保不可变性,避免对象创建后字段被随意修改。
那怎么实现“允许通过CashIn更新余额,但禁止外部随意修改”的需求?
这时候你不该用readonly字段,而是用私有字段+公共只读属性的经典模式,既满足外部只能读取余额的要求,又能让类内部的CashIn方法合法修改余额。代码示例如下:
public class Account { // 私有字段,只有类内部能修改 private decimal _balance; // 公共只读属性,外部只能读取,不能赋值 public decimal Balance => _balance; public Account() { _balance = 0; } public void CashIn(decimal amount) { if (amount <= 0) throw new ArgumentException("存入金额必须大于0,请检查输入"); _balance += amount; } }
这种方式完全符合C#的设计规范,代码可读性和安全性都很高,是实际项目里的标准做法。
有没有“非常规”的办法修改readonly字段?
严格来说,用反射可以绕过编译器的限制,在CashIn里修改readonly字段,但我必须强烈警告你:这是非常糟糕的实践!
反射会破坏readonly的设计意图,绕过编译期的安全检查,不仅代码可读性极差,还可能导致不可预期的行为(比如某些场景下JIT优化会缓存readonly字段的值,导致修改后读取到旧值)。如果非要演示这种写法,代码大概是这样:
public class Account { public readonly decimal balance; public Account() { balance = 0; } public void CashIn(decimal amount) { if (amount <= 0) throw new ArgumentException("存入金额必须大于0,请检查输入"); // 用反射修改readonly字段(强烈不推荐!) var balanceField = typeof(Account).GetField(nameof(balance), System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance); balanceField?.SetValue(this, balance + amount); } }
再次强调:实际项目中绝对不要这么做,这完全违背了C#的设计原则,只会给自己埋坑。
总结
- 如果你需要允许
CashIn修改余额,同时禁止外部随意修改,用「私有字段+公共只读属性」是正确的选择。 readonly字段的设计是为了保证对象初始化后字段值不可变,不要试图在构造外修改它。
内容的提问来源于stack exchange,提问作者jerin sifat
相关产品推荐
相关产品推荐

