C#构造函数执行顺序

web*_*mer 116 c# inheritance constructor constructor-chaining

在C#中,当你这样做时

Class(Type param1, Type param2) : base(param1) 
Run Code Online (Sandbox Code Playgroud)

是先执行的类的构造函数,然后调用超类构造函数还是先调用基础构造函数?

Jon*_*eet 163

订单是:

  • 成员变量初始化为层次结构中所有类的默认值

然后从派生程度最高的类开始:

  • 为最派生类型执行变量初始值设定项
  • 构造函数链将确定要调用哪个基类构造函数
  • 初始化基类(递归所有这些:)
  • 执行此类链中的构造函数体(请注意,如果它们被链接Foo() : this(...)等,则可以有多个构造函数体

请注意,在Java中,在运行变量初始值设定项之前初始化基类.如果你曾经移植任何代码,这是一个重要的区别要知道:)

如果您有兴趣,我有一个页面,其中包含更多详细信息.

  • 似乎我的一半贡献都指向了他的答案; 但Eric Lippert也写了一篇关于这个话题的好文章:http://blogs.msdn.com/ericlippert/archive/2008/02/15/why-do-initializers-run-in-the-opposite-order -as-constructors-part-one.aspx http://blogs.msdn.com/ericlippert/archive/2008/02/18/why-do-initializers-run-in-the-opposite-order-as-constructors-部分two.aspx (6认同)
  • 与 Java 的比较+1。另外,我认为 C++ 也是如此,但我不能 100% 确定。 (2认同)
  • @Jon Skeet:在vb.net中,您可以从派生类初始值设定项调用基类成员。从基类构造函数虚拟调用的派生类方法不能依赖其字段初始值设定项来运行,但我认为依赖派生类字段初始值设定项在基类构造函数之前运行的设计无论如何都有些脆弱,因为它们会不适用于初始化值取决于构造参数的任何场景。 (2认同)
  • @Jon Skeet:不,我的意思是与基类相关的所有内容都在派生类之前执行。实际上,我最喜欢的是允许字段有四种模式的声明:(1)在基本构造函数之前初始化;(2) 在基类构造函数之后进行初始化,并允许在计算中使用基类成员;(3) 从相同名称/格式的构造函数参数进行初始化(每个构造函数都必须具有这些名称和类型的参数,或者链接到具有这些名称和类型的参数),或者 (4) 充当“临时”字段,初始化为#3,但只能从其他初始化器访问。 (2认同)

Yur*_*ich 48

它将首先调用基础构造函数.还要记住,如果你没有把:base(param1)你的构造函数放在后面,那么将调用base的空构造函数.


tan*_*ius 12

首先调用基类的构造函数.


use*_*667 7

不确定这应该是评论/答案,但对于那些通过实例学习的人来说,这个小提琴也说明了顺序:https://dotnetfiddle.net/kETPKP

using System;

// order is approximately
/*
   1) most derived initializers first.
   2) most base constructors first (or top-level in constructor-stack first.)
*/
public class Program
{
    public static void Main()
    {
        var d = new D();
    }
}

public class A
{
    public readonly C ac = new C("A");

    public A()
    {
        Console.WriteLine("A");
    }
    public A(string x) : this()
    {
        Console.WriteLine("A got " + x);
    }
}

public class B : A
{
    public readonly C bc = new C("B");

    public B(): base()
    {
        Console.WriteLine("B");
    }
    public B(string x): base(x)
    {
        Console.WriteLine("B got " + x);
    }
}

public class D : B
{
    public readonly C dc = new C("D");

    public D(): this("ha")
    {
        Console.WriteLine("D");
    }
    public D(string x) : base(x)
    {
        Console.WriteLine("D got " + x);
    }
}

public class C
{
    public C(string caller)
    {
        Console.WriteLine(caller + "'s C.");
    }
}
Run Code Online (Sandbox Code Playgroud)

结果:

D's C.
B's C.
A's C.
A
A got ha
B got ha
D got ha
D
Run Code Online (Sandbox Code Playgroud)