Вызов абстрактного метода в конструкторе абстрактного класса

#c# #.net #constructor #abstract

#c# #.net #конструктор #аннотация

Вопрос:

Как указано в CA2214, не следует вызывать переопределяемый метод в конструкторе. Однако я столкнулся со случаем, когда я не вижу другого способа сделать то, чего я пытаюсь достичь, и я не вижу потенциальных проблем, возникающих из-за нарушения этого правила:

У меня есть абстрактный базовый класс для конфигураций. В этом классе есть логика для получения значений. В моих приложениях есть конфигурации, которые могут состоять из определенных компонентов. Таким образом, мой SpecificConfig будет наследоваться от ConfigBase и состоять из ConfigComponentA и ConfigComponentB:

 public abstract class ConfigBase
{
    protected ConfigBase()
    {
        this.InitializeMembers();
        this.SetConfigValues();
    }

    protected abstract void InitializeMembers();

    private void SetConfigValues() {
        // Set the config values
        // Depends on members initialized in InitializeMembers
    }
}

public class ConfigComponentA
{
    public string FieldA1;
    public string FieldA2;
}

public class ConfigComponentB
{
    public string FieldB1;
    public string FieldB2;
}

public sealed class SpecificConfig : ConfigBase
    public SpecificConfig() : base() {}

    public ConfigComponentA ConfigA;
    public ConfigComponentB ConfigB;

    protected override void InitializeMembers()
    {
        this.ConfigA = new ConfigComponentA();
        this.ConfigB = new ConfigComponentB();
    }
}
  

Главное, что конфигурации могут состоять из разных компонентов, и я хочу избежать дублирования кода, используя логику для извлечения и установки значений конфигурации в SetConfigValues() в базовом классе.

У меня такое чувство, что может быть лучший способ сделать это в целом, но я действительно не вижу никакого неожиданного поведения, которое могло бы из этого получиться. Есть ли лучший подход?

Комментарии:

1. Если это обычная инициализация конфигурации .. тогда я не вижу причин, по которым вы не можете делать то, что у вас есть в данный момент

2. Вы можете сделать SetConfigValues() защищенным и позволить дочерним классам вызывать его самостоятельно после инициализации конфигураций (что в данном случае они делают в конструкторе, в то время как InitializeMembers() удаляется. Или просто отключите это предупреждение, если вы считаете, что проблемы, которые могут возникнуть, неприменимы в вашем случае.

3. Вы также можете рассмотреть фабричный метод, выполняющий построение и инициализацию объекта в два этапа.

4. Зачем нужна эта иерархия классов? ConfigBase Обеспечивает ли какое-то общее поведение для подклассов?