Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Overcoming CA2214 "Do not call overridable methods in constructors"

Consider the following class hierarchy:

public abstract class Base
{
    private readonly string _s;
    protected readonly bool _b = getBool();

    protected Base()
    {
        _s = GetS();
    }

    protected abstract string GetS();
}

public sealed class Derived : Base
{
    public Derived() : base() {}
    
    protected override string GetS() 
    {
        return _b ? "true" : "false";
    }
}

The compiler quite understandably complains with CA2114, since we are calling an overridden method in the base constructor. What is the "best" pattern to avoid this, while having the least impact on the design? I could move the call to GetS() and set _s into the constructor of Derived, but:

  • this would mean removing the readonly attribute from _s;
  • creators of subclasses must remember to set _s themselves.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

As a quick patch I suggest turning _s field into a readonly property:

public abstract class Base {
  protected readonly bool _b;

  // Backing Field for _s
  private string s_s;

  private string _s => s_s ??= GetS();

  protected Base() {
    _b = true;
  }
 
  // Quick patch: I've kept GetS alive
  protected abstract string GetS();
}

As a more elaborated way out I suggest to make the property being abstract (please, note that you have field, method and constructor involved into maintaining _s; let’s combine the relevant code in one property):

public abstract class Base {
  protected readonly bool _b;

  protected abstract string _s { get; }

  protected Base() {
    _b = true;
  }
}

And then

public sealed class Derived : Base {
  public Derived() : base() {}

  protected override string _s => _b ? "true" : "false";
}

If (in some class) you don’t want to compute _s each time, you can perform a lazy computation:

public sealed class DerivedHeavy : Base {
  public DerivedHeavy() : base() {
  }

  private Lazy<string> lazy_s = new Lazy<string>(() => {
    // Heavy Computations here...

    return _b ? "true" : "false";
  });

  protected override string _s => lazy_s.Value;
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading