Принудительная инициализация свойств
Есть абстрактный класс и производные от него.
Мне нужно, чтобы некоторые свойства абстрактного класса были обязательно проинициализированы идвидивидуальными значениями в производных классах, чтобы я при создании этих производных классов, не забыл назначать такому свойству значение в конструкторе производного класса.
Меня не устраивает значение по умолчанию абстрактного класса.
Вот в примере у производного класса 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 значение индивидуальное для производного С класса
}
}
Ответы (2 шт):
Компилятор и так проверяет, что все поля и свойства инициализируются в конструкторе. Можно поднять приоритет этого сообщения (даже именно на этот контруктор с помощью директив препроцессора), чтобы оно вызывало ошибку.
Как вариант, можно в конструкторе абстрактного класса инициализировать переменные значениями, которые вызовут ошибку (правда, это будет ошибка времени исполнения), если в конструктор не были переданы значения для инициализации. Возможно, это не удастся сделать для всех типов данных.
Можно сделать так как я и писал в комментариях:
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 ... };.