Подтвердить что ты не робот

Автоматическое создание базовых конструкторов в производном классе?

У меня есть базовый класс с двумя конструкторами, для которого требуется параметр:

public abstract class StoreBase 
{
    private readonly SomeObject_sobj;

    protected StoreBase(SomeObject sobj)
    {
        _sobj = sobj;
    }

    protected StoreBase(OtherObject oobj)
    {
        _sobj = new SomeObject(oobj);
    }
}

Тогда у меня есть производный класс:

public class MyDerived: StoreBase
{

}

Это приводит к ошибке компиляции как base class doesn't contain parameterless constructor.

Я понимаю, что поскольку MyDerived не содержит конструктора, компилятор добавляет конструктор без параметров (который хорошо известен и не имеет отношения к производным классам). Однако, поскольку он происходит от другого класса, конструктор базового класса должен запускаться первым, и нет способа определить, какой конструктор должен запускаться из пустого конструктора MyDerived.

В основном я спрашиваю: могу ли я избежать копирования/вставки всех конструкторов из класса Base в Derived, если мне действительно не нужна дополнительная логика конструктора? Могу ли я сказать "Возьмите всех конструкторов из базы", ​​не добавляя их все?

(И да, я знаю, что я мог/должен был реорганизовать это в конструктор без параметров и защищенный виртуальный метод Initialize(), но мне все еще интересно, могу ли я работать с конструкторами и все же избегать копирования/вставки)

4b9b3361

Ответ 1

Нет - вам также потребуется реализовать (соответствующие) конструкторы в производном классе.

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

public class MyDerived : StoreBase
{
     public MyDerived(SomeObject sobj) : base(sobj) {}
     public MyDerived(OtherObject  oobj) : base(oobj) {}
}

также:

(И да, я знаю, что я мог/должен был реорганизовать это в конструктор без параметров и защищенный виртуальный метод Initialize(), но мне все еще интересно, могу ли я работать с конструкторами и все же избегать копирования/вставки)

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

public class MyDerived : StoreBase
{
   // .. other stuff
   protected override void Initialize()
   {
       // Leave out, intentionally or accidentally, the following:
       // base.Initialize(); 
   }
}

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

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

Ответ 2

Нет, конструкторы не наследуются и нет ярлыка для создания копий базовых конструкторов.

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

public MyDerived(SomeObject sobj) : base(sobj) {}
public MyDerived(OtherObject oobj) : base(oobj) {}

Ответ 3

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

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

Ответ 4

К сожалению, ответа нет.

Одна вещь, которую вы можете сделать, - это база вызовов из вашего конструктора MyDerived:

class MyDerived: StoreBase
{
public MyDerived(OtherObject obj) : base (obj) {}
}

Ответ 5

Могу ли я сказать "Возьмите все конструкторы из базы", ​​не добавляя их все?

Нет.: - (