Принудительная инициализация свойств

Рейтинг: 1Ответов: 2Опубликовано: 08.05.2023

Есть абстрактный класс и производные от него.

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

Меня не устраивает значение по умолчанию абстрактного класса.

Вот в примере у производного класса C я случаной забыл Prop2 назначить значение.

Как заметить что я забыл ?

    internal abstract class A 
    {
        public string Prop1 { get; protected set; }
        public string Prop2 { get; protected set; }

        public A(string prop) 
        {
            Prop1 = prop;
        }

    }

    internal abstract class B : A
    {
        protected B(string prop) : base(prop)
        {
            Prop2 = "Значение индивидуальное для производного B класса";
        }
    }

    internal abstract class C : A
    {
        protected C(string prop) : base(prop)
        {
            // Забыл добавить в Prop2 значение индивидуальное для производного С класса
        }
    }

Ответы

▲ 1Принят

Можно сделать так как я и писал в комментариях:

internal abstract class A 
{
    public string Prop1 { get; protected set; }
    public string Prop2 { get; protected set; }

    public A(string prop1, string prop2) 
    {
        Prop1 = prop1;
        Prop2 = prop2;
    }

}

internal abstract class B : A
{
    protected B(string prop) : base(prop, "Значение индивидуальное для производного B класса")
    {
    }
}

internal abstract class C : A
{
    // тут будет ошибка
    protected C(string prop)
    {
    }

    // и тут будет ошибка
    protected C(string prop) : base(prop)
    {
    }

    // тут ок
    protected C(string prop) : base(prop, "some value")
    {
    }
}

Если вы используете новые версии языка (required появилось в C# 11), то можно написать так:

internal abstract class A
{
    public required string Prop1 { get; set; }
    public required string Prop2 { get; set; }
}

тогда компилятор будет требовать, чтобы эти свойства были установлины явно, правда он не будет понимать, что эти свойства установлены через конструктор. Т.е. в наследнике вы не сможете в конструторе написать Prop2 = "2". Потом просто создать var c = new C();, он все равно будет требовать var c = new C { Prop1 ..., Prop2 ... };.

▲ 0

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

Как вариант, можно в конструкторе абстрактного класса инициализировать переменные значениями, которые вызовут ошибку (правда, это будет ошибка времени исполнения), если в конструктор не были переданы значения для инициализации. Возможно, это не удастся сделать для всех типов данных.