编译器在编译的时候,会事先分析所需要的静态字段,如果这些静态字段所在的类有静态的构造函数,则忽略静态字段的初始化,否则先进行静态字段的初始化。对类的静态成员初始化的顺序取决于在Main函数中的引用顺序,先引用到的先进行初始化,但如果类的静态成员的初始化依赖于其它类的静态成员,则会先初始化被依赖类的静态成员。而带有静态构造函数的类的静态字段,只有在引用到的时候才进行初始化。
接下来,用实例来对以上的一段总结性的描述逐句分析:
1、编译器在编译的时候,会事先分析所需要的静态字段,如果这些静态字段所在的类有静态的构造函数,则忽略静态字段的初始化,否则先进行静态字段的初始化。
==无静态构造函数:上图中实例的执行流程就是红色数字标记的顺序,首先,在编译器进行编译时,发现Main主函数中会用到A类的静态字段X,所以,会在程序开始执行之前去对能用到的静态字段进行初始化(在无静态构造函数的前提下);B类中的静态字段没有初始化的原因是编译时没有发现用到此静态字段;静态字段在IL中标记为BeforeFliedInit;
将上图中的普通构造函数换为静态构造函数会是什么效果呢?
==静态构造函数:当类A中有静态的构造函数时,其静态字段不再提前去初始化,而是当调用时才进行初始化;当执行完静态字段后,会紧接着去执行静态构造函数中的代码块;值得一说的是,如果A类中有一个静态的方法,当Main函数调用时则先执行A类的静态构造函数,再去执行静态方法;
2、对类的静态成员初始化的顺序取决于在Main函数中的引用顺序,先引用到的先进行初始化(这个就不用写例子了,对于两个相同状态的类(都含有静态构造函数或都没有),其中类静态字段的初始化的顺序都是按照其在Main函数中调用时的顺序执行的),当然如果过一个有静态构造函数,另一个没有静态的构造函数的话,那就另当别论了!
3、如果类的静态成员的初始化依赖于其它类的静态成员,则会先初始化被依赖类的静态成员。
==首先,上图的代码中A类和B类都含有普通的构造函数,并且主程序中都用到了这两个类中的静态字段,那么它们的静态字段就会在主程序运行之前进行初始化,然后当有多个静态字段时,他们的执行顺序就是按照主程序中调用的顺序来执行!如上图:先初始化Y,再初始化X
4、如果类的静态成员的初始化依赖于其它类的静态成员,则会先初始化被依赖类的静态成员
==如上图,在编译器编译时,检测到会用到A类的静态字段,那么就会在Main主函数运行之前对A类的X字段进行初始化,但是X字段中又用到了B类的Y字段,所以就会先初始化B类中的Y字段,再初始化A类的X字段!也就是先初始化被依赖的静态字段。
5、而带有静态构造函数的类的静态字段,只有在引用到的时候才进行初始化。
这里才是博客中主要的,静态构造函数的作用就是不让静态字段在主程序运行之前进行初始化,而是当主程序调用它时才执行,并且紧接着执行该字段索在类的静态构造函数中的代码
==上例中因为A类和B类都含有静态的构造函数,所有就避免了其类中静态字段的提前初始化,当调用用时才执行,并且在上例中A类的X字段又依赖B类的Y字段(因为都是普通的构造函数,所以不会提前执行,而是用到时才执行),所以当程序到达A的X字段时就会去调用B类的Y字段(紧接着执行B类的静态构造函数),回来之后再继续执行A类的静态够走啊函数!
这个博客中写得也非常的详细:博客地址网址
2013-9-22更新
==当第一次调用静态字段时,就会执行所有静态字段,并执行静态构造函数,下次再调用其他静态字段时,就直接取即可,不必在执行一遍User类
==只要使用此类,例如实例化,就会执行类中的静态字段。