Base () и This () в конструкторах. (Цепные конструкторы) - PullRequest
0 голосов
/ 26 июня 2019

У меня есть вопрос, касающийся конструкторов цепочки. Я прочитал некоторые вопросы о StackOverflow и некоторых статьях на C #, но не могу полностью понять тему.Поэтому у меня есть BaseClass, который наследуется DerivedClass.В DerivedClass у меня нет конструктора аргументов, но он вызывает базовый конструктор с помощью: base () и также передает значение.Является ли это основной целью базового ключевого слова, используемого в конструкторе для передачи значения унаследованному классу от производного или что-то большее.А также в производном классе у нас есть второй конструктор, который принимает 1 параметр и его использование: this ().Я не могу понять, почему, когда я удаляю: this () из этого конструктора «VS» говорит мне: «Не существует аргумента, соответствующего необходимому формальному параметру« i »BaseClass.BaseClass (int)? Почему я не могупросто иметь один аргумент конструктора в DerivedClass без использования this ()?

public class BaseClass
{
    protected int _Num;

    public BaseClass(int i)
    {
        _Num = i;
    }

    public int Num { get => this._Num ; set => _Num = value; }
}

public class DerivedClassA : BaseClass
{
    private string _Name;
    private int _AnotherValue;

    public string Name { get => this._Name ; set => this._Name = value; }
    public int AnotherValue { get => this._AnotherValue; set => this._AnotherValue = value; }

    public DerivedClassA() : base(123)
    {
        _Name = "testing";
    }

        public DerivedClassA(int param2) : this()      <-- Why i can't compile the program without the this() keyword here ?
        {
            AnotherValue = param2;
        }
    }

public class Program
{
        public static void Main(string[] args)
        {
            DerivedClassA objA = new DerivedClassA(5);
        }
}

1 Ответ

2 голосов
/ 26 июня 2019

Я не могу найти дубликат, который точно соответствует, поэтому я предоставлю ответ.

Представьте себе следующие классы:

public class Base
{
    public Base()
    {
    }
}

public class Derived : Base
{
    public Derived()
    {
    }
}

Попробуйте онлайн

Когда вы инициализируете производный класс, вы должны сначала инициализировать базу.В нашем примере выше класс Base имеет конструктор без параметров, поэтому производный класс может неявно вызывать его.Если мы добавим базовый второй конструктор, эта логика останется верной, и конструктор без параметров будет по-прежнему неявно вызываться:

public class Base
{
    public Base()
    {
    }

    public Base(int a)
    {
    }
}

public class Derived : Base
{
    public Derived()
    {
    }
}

Попробуйте это онлайн

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

public class Base
{       
    public Base(int a)
    {
    }
}

public class Derived : Base
{
    public Derived() : base(1)
    {
    }
}

Попробуйте это онлайн

Так что же произойдет, если мы добавим дополнительный конструктор производного класса?Ну, это также должно вызвать базовый класс (прямо или косвенно):

public class Base
{       
    public Base(int a)
    {
        // this method body is executed first
    }
}

public class DerivedA : Base
{
    public DerivedA(string name, int val) : base(val)
    {
        // this method body is executed second (last if you used this constructor, e.g. new DerivedA("hello", 1) )
    }

    public DerivedA() : this("test", 5) // this will call the constructor above, which will first call base. So the final chain is: base, constructor above, this constructor
    {
        // this method body is executed third (last if you used this constructor, e.g. new DerivedA() )
    }
}

public class DerivedB : Base
{
    public DerivedB(string name, int val) : base(val)
    {
    }

    public DerivedB() : base(5) // this will call the base constructor, and then this constructor. The constructor above will not be used.
    {

    }
}

Попробуйте это онлайн

Обратите внимание, что все классы имеют конструктор без параметровкогда никакой другой конструктор не определен, следующие два примера эквивалентны:

public class BaseA
{

}

public class BaseB
{
    public BaseB()
    {
    }
}

Вы заметите, что SharpLab показывает, что компилятор удалил пустой конструктор из BaseB(), так как он лишний.

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

public class Base
{       
    public Base()
    {
        // this method body is executed first
        Console.WriteLine("Base constructor");
    }
}

public class Derived : Base
{
}

Попробуйте его в режиме онлайн

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...