Как правильно определить постоянное значение в производном классе с целью проверки параметров в конструктор предка.
Учитывая следующем примере:
public abstract class Polygon
{
protected abstract int VertexCount { get; }
public LineSegment[] Edges { get { /* ... */ } }
public Point2D[] Vertices { get { /* ... */ } }
protected Polygon(Point2D vertices)
{
if(vertices.Length != VertexCount)
threw new ArgumentOutOfRangeException(...);
}
}
public class Triangle: Polygon
{
protected override int VertexCount { get; } = 3;
public Triangle(Point2D[] vertices) : base(vertices){}
}
public class Quadrilateral: Polygon
{
protected override int VertexCount { get; } = 4;
public Quadrilateral(Point2D[] vertices) : base(vertices){}
}
Очевидно, что выше не работает должным образом из-за
Virtual member call in constructor
(да я понимаю предупреждение, я не прошу об этом)
В моей логике (которая вроде бы ущербной), в
VertexCount
является особенностью
Polygon
класса (за фиксированного размера массивов как
Edges
и
Vertices
будет определяться в пределах многоугольника класс) во время инициализации, и варьируется в зависимости от производного класса (следовательно, должен быть определен в производном классе).
Производный класс должен определить стоимость
VertexCount
, потому что он является специфическим для производного класса, однако, базовый класс не знает о производном классе. Это является причиной 'абстрактное инт', чтобы гарантировать, что производный класс переопределяет его. Кроме того,
VertexCount
-это свойство, потому что поля не могут быть абстрактными. Тем не менее, она также должна быть постоянной (потому что треугольник, стороны всегда будут 3 и четырехугольник стороны всегда будет 4).
Наконец, сообщение для
Exception
быть брошенным в базовый конструктор, должно быть что-то вроде:
if(vertices.Length != VertexCount)
threw new ArgumentOutOfRangeException(nameof(vertices),
message: $"A {this.ToString()} requires exactly {VertexCount} vertices, received {vertices.Length}");
Конечно 'это.Метод toString()' часть будет называться в контексте базового класса, а не производного класса (например, решение отражение будет работать здесь)?
Так при всем этом, в качестве альтернативы можно угробить конструктор в базовом классе, создать константу для
VertexCount
в производных классах, и инициализировать и установить все значения в конструкторы производного класса. Кажется, что будет много дублирующегося кода в производных классах (может быть не в пример выше, потому что технически я только дублирующего 2 строк кода в каждом, но что происходит, когда конструктор становится тяжелее).
Что такое 'правильный' способ сделать это с наименьшим количеством повторяющегося кода?