C # 中的基本构造函数-先调用哪个?

哪个首先被调用-基本构造函数还是“这里的其他东西”?

public class MyExceptionClass : Exception
{
public MyExceptionClass(string message, string extrainfo) : base(message)
{
//other stuff here
}
}
76417 次浏览

我觉得是基地

编辑见:

Http://www.c-sharpcorner.com/uploadfile/rajeshvs/consndestructorsincs11122005010300am/consndestructorsincs.aspx

上面写着:

using System;
class Base
{


public Base()
{
Console.WriteLine("BASE 1");
}
public Base(int x)
{
Console.WriteLine("BASE 2");
}
}


class Derived : Base
{
public Derived():base(10)
{
Console.WriteLine("DERIVED CLASS");
}
}


class MyClient
{
public static void Main()
{
Derived d1 = new Derived();
}
}

这个程序输出

基地2

派生课程

将首先调用基构造函数。

试试看:

public class MyBase
{
public MyBase()
{
Console.WriteLine("MyBase");
}
}


public class MyDerived : MyBase
{
public MyDerived():base()
{
Console.WriteLine("MyDerived");
}
}

将调用 Exception 构造函数,然后调用 Child 类构造函数。

简单的 OO 原理

看看这里 Http://www.dotnet-news.com/lien.aspx?id=35151

实际上,派生类构造函数是首先执行的,但是 C # 编译器插入对基类构造函数的调用作为派生构造函数的第一条语句。

所以: 派生是先执行的,但是“看起来”基类是先执行的。

基类构造函数在派生类构造函数之前被调用,但派生类初始值设定项在基类初始值设定项之前被调用。例如:

public class BaseClass {


private string sentenceOne = null;  // A


public BaseClass() {
sentenceOne = "The quick brown fox";  // B
}
}


public class SubClass : BaseClass {


private string sentenceTwo = null; // C


public SubClass() {
sentenceTwo = "jumps over the lazy dog"; // D
}
}

执行顺序是: C,A,B,D。

看看这两篇 msdn 文章:

基本构造函数将首先被调用,否则,在您的“其他内容”必须使用由基本构造函数初始化的成员变量的情况下,您将得到编译时错误,因为您的类成员还没有被初始化。

在子构造函数中完成任何工作之前调用 base (?)。

即使不使用: base ()(在这种情况下,调用0参数的 base 构造函数) ,也是如此

它的工作原理类似于 Java,

public Child()
{
super(); // this line is always the first line in a child constructor even if you don't put it there! ***
}

例外: 我可以用 super (1,2,3)代替。但是如果我没有显式地调用 super,那么 super ()就会被调用。

正如其他人所说的,基本构造函数首先被调用,然而,构造函数并不是第一个发生的事情。

假设你有这样的课程:

class A {}


class B : A {}


class C : B {}

首先,字段初始值设定项将按从派生程度最高的类到派生程度最低的类的顺序调用。首先是 C的字段初始化器,然后是 B,然后是 A

然后以相反的顺序调用构造函数: 首先是 A的构造函数,然后是 B,然后是 C

构造函数调用是从下往上调用(激发) ,并从上往下执行。因此,如果 C 类从 B 类继承,B 类从 A 类继承,当你创建一个 C 类的实例时,C 类的构造函数被调用,C 类的构造函数又调用 B 类的指导函数,B 类的指导函数又调用 A 类的构造函数。现在执行 A 的构造函数,然后执行 B 的构造函数,然后执行 C 的构造函数。

不要试图记住它,试着向自己解释将要发生的事情。假设您有一个名为 Animal 的基类和一个名为 Dog 的派生类。派生类向基类添加一些功能。因此,当执行派生类的构造函数时,基类实例必须是可用的(以便您可以向其添加新功能)。这就是为什么构造函数从基函数执行到派生函数,而析构函数却以相反的方式执行——首先是派生函数,然后是基函数。

(这是简化了的,但它应该能帮助你在将来回答这个问题,而不需要真正记住它。)

Eric Lippert 有一篇关于对象初始化相关问题的有趣文章,解释了构造函数和字段初始化器排序的原因:

为什么初始化器和构造函数的顺序相反? 第一部分
为什么初始化器和构造函数的顺序相反? 第二部分

但是派生类中字段的初始值设定项是首先调用的。

呼叫顺序是

  1. 派生类字段初始值设定项
  2. 基类字段初始值设定项
  3. 基类构造函数基类构造函数
  4. 派生类构造函数

(可以将2和3作为一个整体来构造基类。)

摘自 < em > CSharp 语言规格5.0 :

10.11.3构造函数执行

变量初始化器被转换成赋值语句,这些赋值 语句在调用基类之前执行 这种排序确保所有实例字段 在任何语句之前由它们的变量初始值设定项初始化 将执行具有该实例访问权限的

using System;
class A
{
public A() {
PrintFields();
}
public virtual void PrintFields() {}
}
class B: A
{
int x = 1;
int y;
public B() {
y = -1;
}
public override void PrintFields() {
Console.WriteLine("x = {0}, y = {1}", x, y);
}
}

当使用 new B()创建 B的实例时,如下 产出:

x = 1, y = 0

因为执行了变量初始值设定项,所以 x的值为1 然后调用基类实例构造函数 值为0(int的默认值) ,因为赋值 直到基类构造函数返回之后才执行。 考虑使用实例变量初始化器和 构造函数初始值设定项作为自动插入的语句 在构造函数体之前

using System;
using System.Collections;
class A
{
int x = 1, y = -1, count;
public A() {
count = 0;
}
public A(int n) {
count = n;
}
}
class B: A
{
double sqrt2 = Math.Sqrt(2.0);
ArrayList items = new ArrayList(100);
int max;
public B(): this(100) {
items.Add("default");
}
public B(int n): base(n – 1) {
max = n;
}
}

包含几个变量初始化器; 它还包含构造函数 这两种形式的初始值设定项(基础和此) 下面显示的代码,其中每个注释表示一个自动 插入语句(用于自动插入的 构造函数调用无效,但仅用于 说明机制)。

using System.Collections;
class A
{
int x, y, count;
public A() {
x = 1;                                // Variable initializer
y = -1;                               // Variable initializer
object();                         // Invoke object() constructor
count = 0;
}
public A(int n) {
x = 1;                                // Variable initializer
y = -1;                               // Variable initializer
object();                         // Invoke object() constructor
count = n;
}
}
class B: A
{
double sqrt2;
ArrayList items;
int max;
public B(): this(100) {
B(100);                               // Invoke B(int) constructor
items.Add("default");
}
public B(int n): base(n – 1) {
sqrt2 = Math.Sqrt(2.0);           // Variable initializer
items = new ArrayList(100);   // Variable initializer
A(n – 1);                         // Invoke A(int) constructor
max = n;
}
}