
图3 Test类的IL代码
class Test
{
public static string x = EchoAndReturn("In type initializer");
// Defines a parameterless constructor.
static Test()
{
}
public static string EchoAndReturn(string s)
{
Console.WriteLine(s);
return s;
}
}
上面我们给Test类添加一个静态的构造函数。

图4 Test类的IL代码
通过上面Test类的IL代码的区别我们发现,当Test类包含静态字段,而且没有定义静态的构造函数时,该类会被标记为beforefieldinit。
现在也许有人会问:“被标记为beforefieldinit和没有标记的有什么区别呢”?OK现在让我们通过下面的具体例子看一下它们的区别吧!
class Test
{
public static string x = EchoAndReturn("In type initializer");
static Test()
{
}
public static string EchoAndReturn(string s)
{
Console.WriteLine(s);
return s;
}
}
class Driver
{
public static void Main()
{
Console.WriteLine("Starting Main");
// Invoke a static method on Test
Test.EchoAndReturn("Echo!");
Console.WriteLine("After echo");
Console.ReadLine();
// The output result:
// Starting Main
// In type initializer
// Echo!
// After echo
}
}
我相信大家都可以得到答案,如果在调用EchoAndReturn()方法之前,需要完成静态成员的初始化,所以最终的输出结果如下:

图5输出结果
接着我们在Main()方法中添加string y = Test.x,如下:
public static void Main()
{
Console.WriteLine("Starting Main");
// Invoke a static method on Test
Test.EchoAndReturn("Echo!");
Console.WriteLine("After echo");
//Reference a static field in Test
string y = Test.x;
//Use the value just to avoid compiler cleverness
if (y != null)
{
Console.WriteLine("After field access");
}
Console.ReadKey();
// The output result:
// In type initializer
// Starting Main
// Echo!
// After echo
// After field access
}

图6 输出结果
通过上面的输出结果,大家可以发现静态字段的初始化跑到了静态方法调用之前,Wo难以想象啊!










