首页 > 解决方案 > 派生类实例化 BASE 类的 2 个对象

问题描述

我有一个基本的查询。我有一个空的派生类。我注意到,当我运行下面粘贴的一段代码(在 Linqpad 中运行)时,我最终得到了 4 个 BASE 类的对象。我的理解是,当我们实例化一个派生类对象时,在没有它自己的构造函数的情况下,会调用 BASE 类构造函数,从而产生 1 个派生类实例。

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 ```

标签: c#linqpad

解决方案


您令人惊讶的输出的原因来自以下几行

private static readonly Base1 instance = new Base1();
private static int numInstance = 0;

语言标准说明了字段初始值设定项(https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/classes#variable-initializers)(强调我的)

[...]当一个类被初始化时,该类中的所有静态字段首先被初始化为其默认值,然后静态字段初始化程序以文本顺序执行

因此,您的代码首先创建instance,将其设置numInstances为 1,然后执行numInstance = 0;将字段“重置”为0.

将声明的顺序更改为

private static int numInstance = 0;
private static readonly Base1 instance = new Base1();

产生您期望的结果,因为numInstances在您构造第一个实例之前首先初始化为 0(技术上两次)。或者,您也可以只删除初始化程序,numInstances因为默认值为int0 反正


推荐阅读