Поскольку ваша цель состоит в том, чтобы позволить клиентскому коду вернуть свойство обратно как WheelPart, но установить его только как определенный подкласс, у вас есть несколько вариантов. Хотя боюсь, что ни один из них не очень чистый.
Во-первых, вы можете выдать ошибку времени выполнения, если задан неправильный тип:
public abstract class Car
{
public abstract WheelPart Wheel { get; set; }
}
public class FastCar : Car
{
private FastWheel _wheel;
public override WheelPart Wheel
{
get { return _wheel; }
set
{
if (!(value is FastWheel))
{
throw new ArgumentException("Supplied wheel must be Fast");
}
_wheel = (FastWheel)value;
}
}
}
Но я бы не стал этого делать, поскольку для клиентского кода совершенно неясно, что любой другой тип колеса вызовет исключение, и они не получат обратной связи компилятора.
В противном случае вы могли бы разделить Getter и Setter для свойства, чтобы требуемый тип был очень ясным:
public abstract class Car
{
public abstract WheelPart Wheel { get; }
}
public class FastCar : Car
{
private FastWheel _wheel;
public override WheelPart Wheel
{
get { return _wheel; }
}
public void SetWheel(FastWheel wheel)
{
_wheel = wheel;
}
}
Это гораздо понятнее для клиента, и ИМХО, более удачное решение, если вам абсолютно необходимо представить геттер в качестве базового класса WheelPart.