C#单例模式和静态构造函数 - chunlieater/chunlifeet GitHub Wiki
单例模式可以用两种方法来做: 1 用静态函数赋值。2 用静态构造函数赋值。 构造函数都是私有,静态构造函数是公共,静态构造函数在程序中只执行一次,不能加修饰符,不能有参数。
-
1
-
public static ClassA instance;
-
pullic static ClassA Instance{
-
get{
-
if(instance ==null){
-
instance = new ClassA();
-
}
-
return instance;
-
}
-
}
-
private ClassA(){}
-
2
-
public static ClassB instance;
-
static ClassB{
-
instance = new ClassB();
-
}
-
private ClassB(){}
静态变量的初始化赋值顺序:
静态变量或静态函数被第一次调用时按照以下顺序赋值:1 开辟变量空间,赋默认值(int型为0,object型为null)。2 查看变量列表中是否有赋值,有的话将其赋值。3 运行静态构造函数。 除了第一次调用之外的任何一次调用,都不用再走这个流程,直接返回当前的值就行了,就算是在初始化调用中进行第二次调用也是如此: 例子:
-
public class Chunli{
-
public static string legs = Cammy.legs;
-
static Chunli(){
-
legs += "chunliLegs!"+2;
-
}
-
}
-
public class Cammy{
-
public static string legs = Chunli.legs;
-
static Cammy(){
-
legs += "Cammylegs!"+1;
-
}
-
}
-
console.writeline(Chunli.legs);
-
console.writeline(Cammy.legs);
最后结果是 “Cammylegs1chunlilegs2” "cammylegs1"
分析:根据静态变量初始化的顺序理清即可。首先调用了Chunli.legs,legs变量开始初始化,首先给它赋默认值string.empty,然后看变量列表赋值, = 右边是Cammy.legs,所以Cammy的legs变量开始初始化,同样首先给legs赋默认值string.empty,然后变量列表赋值为 = Chunli.legs,Chunli.legs已经赋值成string.empty了,属于第二次调用,所以直接返回当前值string.empty,Cammy.legs = string.empty,然后再执行cammy的静态构造函数,最后Cammy.legs = string.empty1,并返回给Chunli.legs,最后执行chunli的静态构造函数,最后Chunli.legs = Cammylegs1chunlilegs2。
如果之前没有使用过静态成员变量或者方法,那么类的对象(实例)第一次被创建时,就会自动按照上面的顺序先调用静态流程,然后再进行非静态流程, 也就是说先给静态变量赋默认值,然后赋初始化值,然后调用静态构造函数,之后给非静态变量赋默认值,再赋初值,最后调用非静态构造函数创建实例。如果该类有父类,并且父类的静态成员没有被访问过,那么在其非静态构造函数开始时进行父类的初始化,流程与该类一致,父类初始化完毕,转回子类构造函数继续执行。
- public class StaticTest{
- private static StaticTest _instance;
- public int x;
- static StaticTest(){
-
Console.WriteLine("StaticConstruct");
- }
- public static StaticTest Instance(){
- Console.WriteLine("StaticInstance");
-
if(_instance==null){
-
_instance = new StaticTest();
-
_instance.x = 100;
-
}
-
return _instance;
- }
-
private StaticTest(){
-
Console.WriteLine("Construct");
- }
-
public static void Test(){
-
Console.WriteLine("StaticTest");
- }
- }
- namespace myApp2
- {
-
class Program
-
{
-
static void Main(string[] args)
-
{
-
StaticTest.Test();
-
StaticTest test = StaticTest.Instance();
-
}
-
}
- }
就这个列子分析下,在调用StaticTest.Test()时,系统先走静态初始化流程,也就是给_instance初始化为null,并执行静态构造函数,然后执行StaticTest.Test(),下面调用Instance单例函数时,因为静态初始化流程已经走完一次,所以直接执行该方法,在方法中初始化实例。
如果不先调用StaticTest.Test(),直接执行单例函数,那同理先走静态初始化流程,然后执行StaticTest.Instance()。