我有一个基本的查询。我有一个派生类,这个类是空的,我注意到当我运行下面粘贴的代码(在Linqpad中运行)时,我最终得到4个BASE类的对象。我注意到,当我运行下面粘贴的代码(在Linqpad中运行)时,我最终得到4个BASE类对象。我的理解是,当我们实例化一个派生类对象时,在没有自己的构造函数的情况下,BASE类的构造函数会被调用,从而产生一个派生类的实例。
void Main()
{
NestedS n1 = new NestedS();
NestedS n2 = new NestedS();
NestedS n3 = new NestedS();
}
public class Base1
{
private static readonly Base1 instance = new Base1();
private static int numInstance = 0;
private readonly object lock1 = new object();
public Base1()
{
lock(lock1)
{
numInstance.Dump("before");
numInstance++;
numInstance.Dump("here");
}
}
}
public class NestedS : Base1{
}
这段代码的结果是派生类有4个实例。谁能给我解释一下这背后的原因。
更新:对不起,在这里重新表述我的疑问,把输出也粘贴过来。从输出来看,numInstance应该在第二个实例创建之前就已经被初始化为1了,但是在第二个实例创建的时候还是0。
before
0
here
1
before
0
here
1
before
1
here
2
before
2
here
3 ```
你的惊人输出的原因来自于以下几行代码
private static readonly Base1 instance = new Base1();
private static int numInstance = 0;
语言标准中提到了字段初始化器(https:/docs.microsoft.comen-usdotnetcsharplanguag-referencelanguag-specificationclasses#variable-initializers。)(重点是我)
[...]当一个类被初始化时,该类中的所有静态字段首先被初始化为它们的默认值,然后静态字段初始化器被执行。语序
所以你的代码首先创建了 instance
,其中规定 numInstances
至1和 之后 执行该行 numInstance = 0;
"重置 "该字段为 0
.
将声明的顺序更改为
private static int numInstance = 0;
private static readonly Base1 instance = new Base1();
产生了你所期待的结果,如 numInstances
在构造第一个实例之前,首先被初始化为0(技术上说是两次)。或者,你也可以直接从 numInstances
的默认值,作为 int
反正是0