Search code examples
c#abstract-classreadonly-attribute

abstract class with readonly member


I have a class structure like this where an abstract class A holds an interface IB and a concrete class C in two variables. Which classes get assigned to that interface variable depends on the actual subclass A1, A2 that inherits the abstract class, and need that class C that gets instantiated in the parent class constructor. So what I came up first was this:

abstract class A
{
    protected readonly IB _b;
    protected readonly C _c;

    protected A()
    {
        _c = new C();
    }
}

class B1 : IB
{
   public B1(C c) {}
}

class B2 : IB
{
   public B2(C c) {}
}

class A1 : A
{
    public A1() : base()
    {
        _b = new B1(_c);
    }
}

class A2 : A
{
    public A2() : base()
    {
        _b = new B2(_c);
    }
}

The assignment _b = new B1(_c); doesn´t work because its protected. I also can´t pass the class Bx down to the base constructor, because I need that to be executed before I can instantiate Bx. How else can I achieve my desired outcome?


Solution

  • _b = ... doesn't work because readonly fields can only be initialised in the constructor of the class that declares it, not in a subclass. It's not because _b is protected. The documentation says:

    In a field declaration, readonly indicates that assignment to the field can only occur as part of the declaration or in a constructor in the same class.

    One way to work around this is to have the superclass take in a Func<C, B1>, and initialise _b there.

    protected A(Func<C, IB> bCreator)
    {
        _c = new C();
        _b = bCreator(_c);
    }
    

    then:

    class A1 : A
    {
        public A1() : base(c => new B1(c))
        {
            
        }
    }
    
    class A2 : A
    {
        public A2() : base(c => new B2(c))
        {
            
        }
    }