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
readonlyattribute from_s; - creators of subclasses must remember to set
_sthemselves.
>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;
}