通过运行这个简单的代码:
在我的电脑上输出结果是这样的:
此时没有什么有趣的东西,一切都很合理,但是当我删除MyClassWithStatic的静态构造函数(因此MyClassWithStatic变成这样,而其他所有内容都与之前相同)。
输出结果如下:
所以问题在于:
class Program
{
class MyClassWithStatic
{
public static int Number = SomeService.GetData();
static MyClassWithStatic()
{
Console.WriteLine("static ctor runs");
}
}
class SomeService
{
public static int GetData()
{
Console.WriteLine("GetDataRuns");
return 42;
}
}
static void Main(string[] args)
{
InitService();
var value = MyClassWithStatic.Number;
Console.WriteLine(value);
}
private static void InitService()
{
Console.WriteLine("InitServiceRuns");
}
}
在我的电脑上输出结果是这样的:
意思是首先调用了InitService方法,然后初始化了MyClassWithStatic类的静态字段,接着调用了静态构造函数(实际上通过在ILSpy和IlDasm中查看,我们可以看到静态字段的初始化发生在cctor的开头)。InitServiceRuns
GetDataRuns
static ctor runs
42
此时没有什么有趣的东西,一切都很合理,但是当我删除MyClassWithStatic的静态构造函数(因此MyClassWithStatic变成这样,而其他所有内容都与之前相同)。
class MyClassWithStatic
{
public static int Number = SomeService.GetData();
}
输出结果如下:
这意味着通过移除静态构造函数,静态字段会更早地初始化。由于初始化是静态构造函数的一部分(通过使用ildasm查看),因此效果基本上是静态构造函数被更早地调用。GetDataRuns
InitServiceRuns
42
所以问题在于:
有人能解释这种行为吗?这可能是什么原因?
还有其他事情可以改变静态构造函数的调用时间吗? (例如附加一个分析器或在IIS中运行它等)(我比较了调试、发布模式、x86、x64,所有模式都显示相同的行为)
-这是在.NET 4.6控制台应用程序中完成的。我还切换到.NET 2(应该使用不同的clr运行,并且行为相同,没有任何区别)
-我也尝试过使用.NET core:无论是否使用cctor,InitService方法都会首先被调用。
-我现在完全意识到这个页面:
用户无法控制程序何时执行静态构造函数。
我也知道,在静态构造函数中有很多事情是不应该做的。但不幸的是,我必须处理一个超出我的控制范围的代码,而我所描述的差异会产生巨大的影响。(我也查阅了许多与C# cctor相关的SO问题..)
(第三个问题:) 那么我所描述的整个情况不是有点棘手吗?