Почему мы не можем использовать конструктор с параметром в производных классах

Почему это невозможно? Я получаю следующую ошибку компилятора при создании экземпляра DerivedClass с параметром конструктора:

GenericParameterizedConstructor.DerivedClass не содержит конструктор, который принимает 1 аргумент

Но вызов очень похожего метода работает.

Зачем?

class Program
{
    static void Main(string[] args)
    {
        // This one produces a compile error 
        // DerivedClass cls = new DerivedClass("Some value");

        // This one works;
        DerivedClass cls2 = new DerivedClass();
        cls2.SomeMethod("Some value");
    }
}


public class BaseClass<T>
{
    internal T Value;

    public BaseClass()
    {
    }

    public BaseClass(T value)
    {
        this.Value = value;
    }

    public void SomeMethod(T value)
    {
        this.Value = value;
    }
}

public class DerivedClass : BaseClass<String>
{
}

3 ответа

Решение

Конструкторы не наследуются - это так просто. DerivedClass содержит один конструктор - открытый конструктор без параметров, предоставляемый компилятором по умолчанию, потому что вы не указали никаких конструкторов.

Обратите внимание, что это не имеет ничего общего с генериками. Вы бы увидели то же самое, если бы BaseClass не были общими.

Легко предоставить конструкторы для DerivedClass хоть:

public class DerivedClass : BaseClass<String>
{
    public DerivedClass() : base()
    {
    }

    public DerivedClass(string value) : base(value)
    {
    }
}

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

parentType (int foo) {...}
parentType (string foo) {...}

и производный тип имел один:

производный тип (строка foo) {...}

Каким должен быть эффект new derivedType(7);? Компилятор будет знать, как создать new baseType(7);, но если бы он создал новый "пустой" объект производного типа и затем просто вызвал конструктор родительского типа, результатом был бы derivedType объект, который никогда не запускал derivedTypeСтроительный кодекс. Хотя некоторые классы не будут иметь никаких проблем с этим (и для таких классов, ранее упомянутая гипотетическая функция будет полезна), многие классы будут.

Между прочим, несколько связанная проблема возникает с защищенными конструкторами. В некоторых языках.net, включая, по крайней мере, текущую версию C#, если тип не абстрактный Foo определяет защищенный конструктор, этот конструктор может использоваться только для создания экземпляров производных типов. В других языках, включая текущий vb.net, код в производном типе может вызывать защищенный конструктор базового типа для создания нового экземпляра базового типа.

Производный класс должен выставить конструктор

public class DerivedClass : BaseClass<String>
{
    public DerivedClass(string str) :base(str) {}
}
Другие вопросы по тегам