我知道父类的构造函数先调用然后调用子类。但是为什么在静态构造函数的情况下它首先从派生类执行然后再执行子类?
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();
}
}
}
输出:
子静态构造函数
父静态构造函数
父实例构造函数
子实例构造函数
现在按照 Jeppe Stig Nielsen 建议当我在构造函数中初始化静态字段时,它按以下顺序运行
输出
父静态构造函数
子静态构造函数
父实例构造函数
子实例构造函数
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");
}
}
为什么会出现这种矛盾的行为?
答案 0 :(得分:19)
首先,这种行为完全不矛盾;这一切都符合规则。你只是不知道规则是什么。
你应该阅读我关于实例构造函数的两部分系列文章和关于静态构造函数语义的四部分系列文章。他们从这里开始:
在这里:
http://ericlippert.com/2013/02/06/static-constructors-part-one/
分别
那些应该清楚地回答你的问题,但如果不是100%明确,请让我总结一下。相关规则是:
那么当你执行new Child()
时会发生什么?
所以你去;顺序是Child静态构造函数,然后是Parent静态构造函数,然后是Parent主体,然后是Child主体。
现在让我们看看你的第二个例子。当你说new XyzChild
时会发生什么?
所以你去吧。没有任何不一致之处;这两个规则正确应用。
答案 1 :(得分:6)
Static
构造函数总是在非静态构造函数之前执行。第一次访问类时会调用静态构造函数。
来自MSDN Doc,
答案 2 :(得分:2)
在您的情况下,静态构造函数的运行顺序是未定义的(我认为)。唯一可以保证的是,它们将在创建实例之前运行。
我将您的代码更改为:
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");
}
}
现在重要的是它们运行的顺序,因为它们写入同一个字段。使用我的代码版本,说new XyzChild();
会导致此输出:
parent static
child static
parent instance
child instance
编辑:Eric Lippert的回答给出了更准确的解释。以上代码仅在静态构造函数的 end 处执行WriteLine
。在静态构造函数的开头处添加其他WriteLine
,以查看XyzParent
静态构造函数是否在XyzChild
静态执行的“中间”运行构造