C#抽象类含readonly成员,子类无法赋值父类protected字段如何解决?
问题核心原因
C#语法规定readonly字段仅能在所属类本身的构造函数中完成赋值,子类构造函数不允许修改父类定义的readonly字段,因此你之前的赋值操作会编译报错。
下面按推荐优先级给出可行实现方案:
方案1:父类构造接收IB工厂委托(最优方案)
通过传入Func<C, IB>类型的工厂委托,既保证执行顺序(父类先初始化C,再调用委托生成IB实例),又能在父类构造中完成_b的readonly赋值,完全保留不可变性约束。
代码实现:
abstract class A { protected readonly IB _b; protected readonly C _c; // 父类构造接收工厂委托 protected A(Func<C, IB> bFactory) { _c = new C(); // 先初始化C,再生成IB实例赋值给readonly字段 _b = bFactory(_c); } } class B1 : IB { public B1(C c) {} } class B2 : IB { public B2(C c) {} } class A1 : A { public A1() : base(c => new B1(c)) { // 无需额外处理_b赋值 } } class A2 : A { public A2() : base(c => new B2(c)) { } }
方案优势:无额外性能开销,完全保留字段不可变性,依赖关系清晰。
方案2:抽象工厂方法+Lazy延迟初始化
如果不想使用委托,可以在父类定义抽象的IB实例创建方法,配合Lazy实现只读、单次初始化的效果:
abstract class A { protected readonly C _c; // Lazy保证仅初始化一次,实现等效readonly的效果 protected readonly Lazy<IB> _b; protected A() { _c = new C(); _b = new Lazy<IB>(() => CreateBInstance(_c)); } // 子类实现该方法返回对应IB实例 protected abstract IB CreateBInstance(C c); } class A1 : A { protected override IB CreateBInstance(C c) { return new B1(c); } } class A2 : A { protected override IB CreateBInstance(C c) { return new B2(c); } }
方案优势:代码可读性高,子类仅需关注IB实例的创建逻辑,天然保证_b不可修改。
方案3:去掉readonly修饰(不推荐)
如果接受放弃编译期不可变性校验,可以将_b的readonly修饰去掉,改为带protected setter的属性,这样子类构造可以直接赋值:
abstract class A { protected IB _b { get; set; } protected readonly C _c; protected A() { _c = new C(); } }
方案劣势:无法保证_b仅被赋值一次,存在后续被意外修改的风险,仅做临时兼容方案使用。
内容的提问来源于stack exchange,提问作者downforme
相关产品推荐
相关产品推荐

