如何让抽象类中的属性仅能在子类构造函数中赋值?
问题:抽象类中仅get属性如何限制子类仅在构造函数中赋值
原本在具体类中有一个仅含get访问器的属性,按照定义它只能在该类的构造函数中赋值。现在需要将这个属性移到无构造函数的抽象类中,子类继承该抽象类后,如何保证抽象类中的这个属性仅能在子类的构造函数中被赋值?
以下方案已被排除:
- 为属性添加
protected set修饰符:会让子类获得超出需求的权限(子类的任意方法都能修改属性,不止构造函数) - 使用
init访问器:不符合仅在构造函数中赋值的要求(init允许在对象初始化器中赋值,范围更广) - 直接依赖
readonly字段的便捷写法:当前使用C# 7.3版本,不支持相关特性
原始代码示例
最初的具体类
public class FooOriginal { public int IntHere { get; } }
重构后的抽象类
public abstract class FooAbstract { public int IntHere { get; } }
编译失败的子类
public class FooChild : FooAbstract { public FooChild() { // 无法编译:IntHere是仅get属性,子类无法直接赋值 IntHere = 3; } }
可行解决方案(适配C# 7.3)
通过将抽象类的属性拆分为protected readonly底层字段+仅get的公开属性,既满足子类仅能在构造函数中赋值,又严格限制权限:
修改后的抽象类
public abstract class FooAbstract { // protected readonly字段:子类仅能在构造函数中赋值 protected readonly int _intHere; // 公开的仅get属性,对外暴露字段值 public int IntHere => _intHere; }
正确赋值的子类
public class FooChild : FooAbstract { public FooChild() { // 仅能在构造函数中给readonly字段赋值,符合要求 _intHere = 3; } }
方案说明
protected readonly字段的特性:子类可以在自身构造函数中赋值,但无法在其他方法中修改,完美匹配“仅构造函数赋值”的需求- 公开的
IntHere属性仅提供get访问器,外部代码无法修改属性值 - 完全适配C# 7.3版本,无需依赖更高版本的语法特性
- 避免了
protected set带来的过度权限问题
内容的提问来源于stack exchange,提问作者J. Mini
相关产品推荐
相关产品推荐

