gpt4 book ai didi

c# - 静态构造函数和实例构造函数的调用

转载 作者:太空狗 更新时间:2023-10-29 20:44:50 24 4
gpt4 key购买 nike

据我所知,先调用父类的构造函数,然后调用子类。但是为什么在静态构造函数的情况下,它先从派生类执行,然后再从子类执行?

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Child t = new Child();
}
}

class Parent
{
public Parent()
{
Console.WriteLine("Parent Instance Constructor");
Console.ReadKey();
}
static Parent()
{
Console.WriteLine("Parent Static Constructor");
Console.ReadKey();
}
}
class Child : Parent
{
public Child()
{
Console.WriteLine("Child Instance Constructor");
Console.ReadKey();
}

static Child()
{
Console.WriteLine("Child Static Constructor");
Console.ReadKey();
}
}
}

输出:

Child Static Constructor

Parent Static Constructor

Parent Instance Constructor

Child Instance Constructor

现在根据 Jeppe Stig Nielsen 建议,当我在构造函数中初始化静态字段时,它按以下顺序运行

输出

Parent Static Constructor

Child Static Constructor

Parent Instance Constructor

Child Instance Constructor

class XyzParent
{
protected static int FieldOne;
protected int FieldTwo;

static XyzParent()
{
// !
FieldOne = 1;
Console.WriteLine("parent static");
}
internal XyzParent()
{
// !
FieldOne = 10;
// !
FieldTwo = 20;
Console.WriteLine("parent instance");
}
}

class XyzChild : XyzParent
{
static XyzChild()
{
// !
FieldOne = 100;
Console.WriteLine("child static");
}
internal XyzChild()
{
// !
FieldOne = 1000;
// !
FieldTwo = 2000;
Console.WriteLine("child instance");
}
}

为什么会出现这种矛盾的行为?

最佳答案

首先,行为一点也不矛盾;这一切都符合规则。你只是不知道规则是什么。

您应该阅读我关于实例构造函数的两部分系列和关于静态构造函数语义的四部分系列。他们从这里开始:

http://blogs.msdn.com/b/ericlippert/archive/2008/02/15/why-do-initializers-run-in-the-opposite-order-as-constructors-part-one.aspx

这里:

http://ericlippert.com/2013/02/06/static-constructors-part-one/

分别。

这些应该清楚地回答了你的问题,但如果不是 100% 清楚,让我总结一下。相关规则是:

  • 规则一:静态构造函数在访问任何静态字段之前、在执行任何静态方法之前以及在执行任何实例构造函数之前运行。
  • 规则二:派生类实例构造函数在运行派生类实例构造函数体之前调用基类实例构造函数。

那么当你执行 new Child() 时会发生什么?

  • 规则一适用。我们即将调用Child的实例构造函数,所以首先要调用Child的静态构造函数。所以它先运行。
  • Child的静态构造函数返回后,Child的实例构造函数运行。规则二适用:Child 实例构造函数在运行其主体之前所做的第一件事是运行 Parent 的实例构造函数。
  • 规则一再次适用。我们即将调用Parent的实例构造函数,所以首先要调用Parent的静态构造函数。所以它运行。
  • Parent的静态构造函数返回后,Parent的实例构造函数运行。规则二适用:它调用对象的实例构造函数,它不做任何有趣的事情,然后运行 ​​Parent 的实例构造函数的主体。
  • 控制权返回到Child的实例构造函数,其主体运行。

就这样吧;顺序是 Child 静态构造函数,然后是 Parent 静态构造函数,然后是 Parent 主体,然后是 Child 主体。

现在让我们看看你的第二个例子。当你说 new XyzChild 时会发生什么?

  • 规则一适用。我们即将调用XyzChild的实例构造函数,所以我们先调用XyzChild的静态构造函数。它的 body 开始执行,并且...
  • ...规则一再次适用。我们即将访问 XyzParent 的静态字段,因此必须执行 XyzParent 的静态构造函数。
  • XyzParent 的静态构造函数执行。它访问了一个字段,但是静态构造函数已经在这个线程上运行了,所以它不会再次递归触发静态构造函数。它打印出它在父级中。
  • 控制权返回到 child 的静态构造函数,它打印出它在 child 中。
  • 现在 child 的实例构造函数可以运行了。规则二适用:XyzParent 的实例构造函数首先运行。
  • 规则一适用,但 XyzParent 的静态构造函数已经运行,因此被跳过。
  • XyzParent 的实例构造函数的主体执行并将控制返回给 XyzChild 的静态构造函数。
  • XyzChild 实例构造函数的主体运行。

就这样吧。没有任何不一致之处;正确应用了这两条规则。

关于c# - 静态构造函数和实例构造函数的调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15462164/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com