静态初始化(转)


但要是在Main()里添加一行:

C#代码 复制代码 收藏代码
  1. using System;   
  2.   
  3. public class Singleton {   
  4.     public static Singleton Instance = new Singleton();   
  5.   
  6.     private Singleton() {   
  7.         Console.WriteLine("Singleton()");   
  8.     }   
  9. }   
  10.   
  11. static class Program {   
  12.     static void Main(string[] args) {   
  13.         Console.WriteLine("Main()");   
  14.         var s = Singleton.Instance;   
  15.         Console.WriteLine("leaving Main()");   
  16.     }   
  17.   
  18.     static void Foo() {   
  19.         var s = Singleton.Instance;   
  20.     }   
  21. }  
using System;

public class Singleton {
    public static Singleton Instance = new Singleton();

    private Singleton() {
        Console.WriteLine("Singleton()");
    }
}

static class Program {
    static void Main(string[] args) {
        Console.WriteLine("Main()");
        var s = Singleton.Instance;
        Console.WriteLine("leaving Main()");
    }

    static void Foo() {
        var s = Singleton.Instance;
    }
}


输出结果跟想像的可能就不一样了:

引用
Singleton()
Main()
leaving Main()


这是因为C#中直接在静态变量声明的地方就初始化,而且没有显式提供静态构造器实现的话,会使类带上beforefieldinit标记,使得类的静态初始化提早执行。稍微改改,给Singleton类添加一个空的静态构造器的话……

C#代码 复制代码 收藏代码
  1. using System;   
  2.   
  3. public class Singleton {   
  4.     public static Singleton Instance = new Singleton();   
  5.   
  6.     static Singleton() {   
  7.     }   
  8.   
  9.     private Singleton() {   
  10.         Console.WriteLine("Singleton()");   
  11.     }   
  12. }   
  13.   
  14. static class Program {   
  15.     static void Main(string[] args) {   
  16.         Console.WriteLine("Main()");   
  17.         var s = Singleton.Instance;   
  18.         Console.WriteLine("leaving Main()");   
  19.     }   
  20.   
  21.     static void Foo() {   
  22.         var s = Singleton.Instance;   
  23.     }   
  24. }  
using System;

public class Singleton {
    public static Singleton Instance = new Singleton();

    static Singleton() {
    }

    private Singleton() {
        Console.WriteLine("Singleton()");
    }
}

static class Program {
    static void Main(string[] args) {
        Console.WriteLine("Main()");
        var s = Singleton.Instance;
        Console.WriteLine("leaving Main()");
    }

    static void Foo() {
        var s = Singleton.Instance;
    }
}


会发现执行结果变为:

引用
Main()
Singleton()
leaving Main()


这种写法就不会使类带上beforefieldinit,于是初始化时间就跟“想像中”的一样,哪儿用到哪儿才初始化。把Instance的初始化整个挪到静态构造器里的结果也一样。

有时候费了力气去写个double-check搞不好还写错了,要是回头发现其实不用自己费神写lazy逻辑也能达到效果的话,那肯定郁闷坏了。引用老赵的帖的标题:如果是能简单解决的问题,就不用想得太复杂了

原文地址:https://www.cnblogs.com/yinxingyeye/p/2442567.html