但要是在Main()里添加一行:
- 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;
- }
- }
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()
Main()
leaving Main()
这是因为C#中直接在静态变量声明的地方就初始化,而且没有显式提供静态构造器实现的话,会使类带上beforefieldinit标记,使得类的静态初始化提早执行。稍微改改,给Singleton类添加一个空的静态构造器的话……
- 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;
- }
- }
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()
Singleton()
leaving Main()
这种写法就不会使类带上beforefieldinit,于是初始化时间就跟“想像中”的一样,哪儿用到哪儿才初始化。把Instance的初始化整个挪到静态构造器里的结果也一样。
有时候费了力气去写个double-check搞不好还写错了,要是回头发现其实不用自己费神写lazy逻辑也能达到效果的话,那肯定郁闷坏了。引用老赵的帖的标题:如果是能简单解决的问题,就不用想得太复杂了