构造函数中的Base()和This()。 (链式构造函数)

时间:2019-06-26 04:52:54

标签: c# constructor

我有一个关于链构造函数的问题,我在StackOverflow和c#文章中读了一些问题,但是我不能完全理解该主题。所以我有一个由DerivedClass继承的BaseClass。在DerivedClass中,我没有参数构造函数,但是它使用以下方法调用基本构造函数:base(),并且还传递了一个值。这是构造函数中用来将值传递给派生类的继承类的基本关键字的主要目的,还是其他用途。同样在派生类中,我们还有另一个构造函数,该构造函数采用1个参数及其使用方式:this()。我不明白为什么要删除:为什么从这个构造函数“ VS”中的this()告诉我“没有给定对应于BaseClass.BaseClass(int)的形式参数“ i”的参数?为什么我不能只是在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 个答案:

答案 0 :(得分:2)

我找不到完全匹配的重复项,因此我将提供答案。

想象一下这些课程:

public class Base
{
    public Base()
    {
    }
}

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

Try it online

初始化派生类时,必须首先初始化基类。在上面的示例中,Base类具有无参数构造函数,因此派生类可以隐式调用它。如果我们添加基本的第二个构造函数,则此逻辑保持不变,并且无参数构造函数仍将隐式调用:

public class Base
{
    public Base()
    {
    }

    public Base(int a)
    {
    }
}

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

Try it online

但是如果我们删除无参数构造函数,则派生现在必须显式调用基本构造函数:

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

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

Try it online

那么,如果我们添加一个额外的派生类构造函数会怎样?嗯,这还必须调用基类(直接或间接):

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.
    {

    }
}

Try it online

请注意,当未定义其他构造函数时,所有类都具有无参数构造函数,因此以下两个示例是等效的:

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
{
}

Try it online

因此,请总结一下:除非您的基类具有无参数构造函数,否则您的派生类构造函数必须直接调用基本构造函数,或通过另一个派生类构造函数间接调用。显然,与任何其他类实例化一样,您只需要调用一个基本构造函数方法即可。只要您可以使用自己拥有的值构造基础,就不需要为每个基础方法都匹配派生方法。