是否会自动调用基类构造函数?

Iva*_* Li 94 c# constructor base-class

class Person
{
    public int age;
    public Person()
    {
        age = 1;
    }
}

class Customer : Person
{
    public Customer()
    {
        age += 1;
    }
}

Customer customer = new Customer();
Run Code Online (Sandbox Code Playgroud)

客户的年龄是2岁吗?似乎无论如何都会调用基类的构造函数.如果是这样,我们为什么base有时需要打电话?

public Customer() : base()
{
    .............
}
Run Code Online (Sandbox Code Playgroud)

Tej*_*ejs 86

这就是C#的工作方式.类型层次结构中每种类型的构造函数将按Most Base - > Most Derived的顺序调用.

所以在你的特定实例中,它调用Person(),然后Customer()在构造函数中.您需要有时使用base构造函数的原因是当前类型下面的构造函数需要其他参数.例如:

public class Base
{
     public int SomeNumber { get; set; }

     public Base(int someNumber)
     {
         SomeNumber = someNumber;
     }
}

public class AlwaysThreeDerived : Base
{
    public AlwaysThreeDerived()
       : base(3)
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

为了构造一个AlwaysThreeDerived对象,它有一个无参数的构造函数.但是,Base类型没有.因此,为了创建无参数构造函数,您需要为基本构造器提供一个参数,您可以对该base实现执行此操作.

  • 你说的是真的。但是,除了将 SomeNumber 设置为随机数的参数化构造函数之外,没有什么可以阻止 Base 使用无参数构造函数。AlwaysThreeDerived 仍将使用 base(3) 调用,但另一个类(称为 RandomDerived)可以从 base 派生,而无需指定无参数的 Base 构造函数。 (2认同)
  • 奇怪的是,Visual Studio在Base构造函数上显示0个引用.这可能导致错误的代码解释. (2认同)

das*_*ght 49

是的,将自动调用基类构造函数.base()当存在没有参数的构造函数时,您不需要添加显式调用.

您可以通过在施工后打印出客户的年龄来轻松测试这一点(通过演示链接到ideone).


Sci*_*ion 11

如果您没有默认的无参数构造函数,那么需要使用参数调用一个:

class Person
{
    public Person(string random)
    {

    }
}

class Customer : Person
{
    public Customer(string random) : base (random)
    {

    }
}
Run Code Online (Sandbox Code Playgroud)


Pra*_*rma 7

base() 默认情况下被调用,但它可以用于其他目的,例如:

  1. base()` 方法用于将值传递给父类构造或
  2. 调用父类的无参数构造函数。

例如:

情况 1:如果父级具有参数化构造函数但没有默认或无参数构造函数。

 class Person
 {

    private string FirstName;
    private string LastName;
    private string EmailAddress;
    private DateTime DateOfBirth;

    public Person(string firstName, string lastName, string emailAddress, DateTime dateOfBirth)
    {
        FirstName = firstName;
        LastName = lastName;
        EmailAddress = emailAddress;
        DateOfBirth = dateOfBirth;

    }
    }
class Employee : Person
{
    private double Salary { get; set; } = 0;

    public Employee(string firstName, string lastName, string emailAddress, DateTime dateOfBirth,double salary)
        :base(firstName,lastName,emailAddress,dateOfBirth)// used to pass value to parent constructor and it is mandatory if parent doesn't have the no-argument constructor.
    {
        Salary = salary;
    }
}
Run Code Online (Sandbox Code Playgroud)

情况 2:当父级有多个构造函数和默认构造函数时。

class Person
{

    private string FirstName;
    private string LastName;
    private string EmailAddress;
    private DateTime DateOfBirth;

    public Person()
    {
        // some important intialization's to be done  

    }

    public Person(string firstName, string lastName, string emailAddress, DateTime dateOfBirth)
    {
        FirstName = firstName;
        LastName = lastName;
        EmailAddress = emailAddress;
        DateOfBirth = dateOfBirth;

    }
    }
class PermanentEmployee : Person
{
    public double HRA { get; set; }
    public double DA { get; set; }
    public double Tax { get; set; }
    public double NetPay { get; set; }
    public double TotalPay { get; set; }

    public PermanentEmployee(double hRA, double dA, double tax, double netPay, double totalPay) : base();
    {
        HRA = hRA;
        DA = dA;
        Tax = tax;
        NetPay = netPay;
        TotalPay = totalPay;
    }
}
Run Code Online (Sandbox Code Playgroud)

在这里,我们通过 base() 手动调用无参数构造函数来执行一些初始化,但不传递任何值。

希望这会帮助你。


Sto*_*ely 6

在使用基类和派生类的 c# 中,必须对派生类的基类中的某些构造函数进行一些隐式或显式调用。

在我意识到这个事实之前,我不明白这一切是如何运作的。

换句话说,当您将基类连接到派生类时,必须从派生类中调用基类中的某些构造函数。基类总是首先通过调用基类中的某些构造函数从派生类实例化。C# 不关心它是默认构造函数还是带参数的非默认构造函数。这就是为什么您可以在所有类中省略默认构造函数,因为它只有在基类中没有添加其他带有参数的非构造函数时才隐式调用。

当您突然添加带有参数的非默认构造函数时,它会破坏默认隐藏的默认构造函数链的创建和调用。在具有非默认构造函数的基类中,您现在必须从派生类显式调用该构造函数或在基类中显式添加默认构造函数。

让我们测试一下这个......

// THIS WORKS!!!
class MyBaseClass0
{
    // no default constructor - created automatically for you
}
class DerivedClass0 : MyBaseClass0
{
    // no default constructor - created automatically for you and calls the base class default constructor above
}

// THIS WORKS!!!
class MyBaseClass1
{
    // same as above
}
class DerivedClass1 : MyBaseClass1
{
    public DerivedClass1()
    {
      // here the derived class default constructor is created explicitly but the call to the base class default constructor is implicitly called
    }
}

// AND THIS WORKS!!!
class MyBaseClass2
{
    // as above
}
class DerivedClass2 : MyBaseClass2
{
    public DerivedClass2() : base()
    {
       // here we explicitly call the default constructor in the base class using base(). note its optional as base constructor would be called anyway here
    }
}

// AND THIS WORKS!!!
class MyBaseClass3
{
    // no default constructor
}
class DerivedClass3 : MyBaseClass3
{
    public DerivedClass3(int x)//non-default constructor
    {
       // as above, the default constructor in the base class is called behind the scenes implicitly here
    }
}

// AND THIS WORKS
class MyBaseClass4
{
    // non default constructor but missing default constructor
    public MyBaseClass4(string y)
    {

    }
}
class DerivedClass4 : MyBaseClass4
{
    // non default constructor but missing default constructor
    public DerivedClass4(int x) : base("hello")
    {
       // note that here, we have fulfilled the requirement that some constructor be called in base even if its not default
    }
}

// BUT THIS FAILS!!!...until you either add in a base() call to the non-default constructor or add in the default constructor into base!
class MyBaseClass5
{
    // 1. EITHER ADD MISSING DEFAULT CONSTRUCTOR HERE AND CALL IT USING base() below....
    public MyBaseClass5() { }

    // 2. Or use the non-default constructor and call to base("hello") below
    //public MyBaseClass5(string y)
    //{
    //}
}
class DerivedClass5 : MyBaseClass5
{
    public DerivedClass5(int x) : base()// 1. Either ADD explicit call here to explicit default constructor in base class
    {
    }

    //public DerivedClass5(int x) : base("hello")// 2. Or ADD explicit call here to parameter-based constructor in base class
    //{
    //}
}
Run Code Online (Sandbox Code Playgroud)

上述所有项目工作的原因是: 1. 基类中对默认构造函数的调用是在基类中隐式创建的,并从派生类中隐式调用,因为基类中没有添加非默认构造函数或 2 . 使用 base(myparamter) 显式调用非默认的、基于参数的构造函数

  • 令人困惑的是默认构造函数何时以及为何在基类中创建并从派生类中调用。只有在基类中没有出现非默认构造函数时才会发生这种情况。