You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 18:39:03