方法一:只适用于单线程环境,不推荐
将构造函数设置为私有函数以禁止他人创建实例
public sealed class Singleton1 { private Singleton1() { } private static Singleton1 instance = null; public static Singleton1 Instance { get { if (instance == null) instance = new Singleton1(); return instance; } } }
方法二:支持多线程环境,但效率不高,不推荐
public sealed class Singleton2 { private Singleton2() { } private static readonly object syncObj = new object(); private static Singleton2 instance = null; public static Singleton2 Instance { get { lock (syncObj) { if (instance == null) instance = new Singleton2(); } return instance; } } }
每次通过Instance得到Singleton2的实例,都会试图加上一个锁,而加锁是比较耗时的操作。
方法三:加锁前后判断实例是否存在,代码较复杂
public sealed class Singleton3 { private Singleton3() { } private static object syncObj = new object(); private static Singleton3 instance = null; public static Singleton3 Instance { get { if (instance == null) { lock (syncObj) { if (instance == null) instance = new Singleton3(); } } return instance; } } }
方法四:使用静态构造函数,推荐
public sealed class Singleton4 { private Singleton4() { Console.WriteLine("An instance of Singleton4 is created."); } public static void Print() { Console.WriteLine("Singleton4 Print"); } private static Singleton4 instance = new Singleton4(); public static Singleton4 Instance { get { return instance; } } }
.NET运行时能够确保只调用一次静态构造函数,C#调用静态构造函数的时机不是由程序员掌控的,而是.NET运行时发现第一次使用一个类型的时候自动调用该类型的静态构造函数。缺点:会过早的创建实例,从而降低内存的使用效率。
方法五:按需创建实例,推荐
public sealed class Singleton5 { private Singleton5() { Console.WriteLine("An instance of Singleton5 is created."); } public static void Print() { Console.WriteLine("Singleton5 Print"); } public static Singleton5 Instance { get { return Nested.instance; } } class Nested { static Nested() { } internal static readonly Singleton5 instance = new Singleton5(); } }
内部定义私有类型Nested,第一次用到这个嵌套类型时会调用静态构造函数创建Singleton5的实例instance。由于Nested为私有的,他人不发使用Nested类型。当不调用Singleton.Instance,就不会触发.NET运行时调用Nested,也不会创建实例,这样就做到了按需创建。