首先调用哪个 - 基础构造函数或"其他东西"?
public class MyExceptionClass : Exception
{
public MyExceptionClass(string message, string extrainfo) : base(message)
{
//other stuff here
}
}
Run Code Online (Sandbox Code Playgroud)
Sam*_*rum 143
基类构造函数在派生类构造函数之前调用,但派生类初始化程序在基类初始化程序之前调用.例如,在以下代码中:
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
}
}
Run Code Online (Sandbox Code Playgroud)
执行顺序为:C,A,B,D.
看看这两篇msdn文章:
cra*_*igb 108
首先调用基础构造函数.
试试吧:
public class MyBase
{
public MyBase()
{
Console.WriteLine("MyBase");
}
}
public class MyDerived : MyBase
{
public MyDerived():base()
{
Console.WriteLine("MyDerived");
}
}
Run Code Online (Sandbox Code Playgroud)
Dav*_*uda 36
不要试图记住它,试着向自己解释一下会发生什么.想象一下,你有一个名为Animal的基类和一个名为Dog的派生类.派生类为基类添加了一些功能.因此,当执行派生类的构造函数时,基类实例必须可用(以便您可以向其添加新功能).这就是为什么构造函数从基础执行到派生但是析构函数以相反的方式执行 - 首先是派生的析构函数,然后是基础析构函数.
(这是简化的,但它可以帮助你在将来回答这个问题,而不需要实际记住它.)
Pao*_*sco 21
实际上,首先执行派生类构造函数,但C#编译器将对基类构造函数的调用作为派生构造函数的第一个语句插入.
所以:派生首先执行,但它"看起来"首先执行了基础.
正如其他人所说的那样,首先调用基础构造函数.然而,构造函数并不是真正发生的第一件事.
假设您有这样的课程:
class A {}
class B : A {}
class C : B {}
Run Code Online (Sandbox Code Playgroud)
首先,将按照从大多数派生到最少派生的类的顺序调用字段初始值设定项.所以第一场初始值C,然后B,然后A.
然后,构造函数将被调用以相反的顺序:首先A的构造函数,然后B,然后C.
我会说基地
编辑见:
那里说:
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();
}
}
Run Code Online (Sandbox Code Playgroud)
这个程序输出
基地2
派生类
首先调用基础构造函数。但派生类中字段的初始值设定项首先被调用。
\n\n调用顺序是
\n\n(可以将2和3视为一个整体来构造基类。)
\n\n\n\n\n\n10.11.3 构造函数执行
\n\n变量初始值设定项被转换为赋值语句,并且这些赋值语句在调用基类实例构造函数之前执行。此顺序确保在执行有权访问该实例的任何语句之前,所有实例字段都由其变量初始值设定项初始化。给出例子
\n\nRun Code Online (Sandbox Code Playgroud)\n\nusing System;\nclass A\n{\n public A() {\n PrintFields();\n }\n public virtual void PrintFields() {}\n}\nclass B: A\n{\n int x = 1;\n int y;\n public B() {\n y = -1;\n }\n public override void PrintFields() {\n Console.WriteLine("x = {0}, y = {1}", x, y);\n }\n}\n当
\n\nnew B()用于创建 的实例时B,将产生以下\n 输出:Run Code Online (Sandbox Code Playgroud)\n\nx = 1, y = 0\n的值为
\n\nx1,因为变量初始值设定项是在调用基类实例构造函数之前执行的。但是,\n 的值为y0(an 的默认值int),因为直到基类构造函数返回之后才执行 to 的赋值y。\n 将实例变量初始值设定项和构造函数初始值设定项视为\n 很有用在构造函数主体之前自动插入\n 的语句。这个例子Run Code Online (Sandbox Code Playgroud)\n\nusing System;\nusing System.Collections;\nclass A\n{\n int x = 1, y = -1, count;\n public A() {\n count = 0;\n }\n public A(int n) {\n count = n;\n }\n}\nclass B: A\n{\n double sqrt2 = Math.Sqrt(2.0);\n ArrayList items = new ArrayList(100);\n int max;\n public B(): this(100) {\n items.Add("default");\n }\n public B(int n): base(n \xe2\x80\x93 1) {\n max = n;\n }\n}\n包含几个变量初始值设定项;它还包含两种形式的构造函数初始值设定项(base 和 this)。该示例对应于下面所示的代码,其中每个注释表示自动插入的语句(用于自动插入的构造函数调用的语法无效,但仅用于说明机制)。
\n\nRun Code Online (Sandbox Code Playgroud)\nusing System.Collections;\nclass A\n{\n int x, y, count;\n public A() {\n x = 1; // Variable initializer\n y = -1; // Variable initializer\n object(); // Invoke object() constructor\n count = 0;\n }\n public A(int n) {\n x = 1; // Variable initializer\n y = -1; // Variable initializer\n object(); // Invoke object() constructor\n count = n;\n }\n}\nclass B: A\n{\n double sqrt2;\n ArrayList items;\n int max;\n public B(): this(100) {\n B(100); // Invoke B(int) constructor\n items.Add("default");\n }\n public B(int n): base(n \xe2\x80\x93 1) {\n sqrt2 = Math.Sqrt(2.0); // Variable initializer\n items = new ArrayList(100); // Variable initializer\n A(n \xe2\x80\x93 1); // Invoke A(int) constructor\n max = n;\n }\n}\n