11.29.07
Implementing the Singleton Pattern in C#
基本上 Singleton Pattern 可以有很多實作方法
而 Singleton Pattern 中比較重要的考量點有兩個
- Thread Safe
- Lazy Binding
在C#中,最簡單的實作方式就是
public sealed class Singleton { static Singleton instance = null; Singleton() {} public static Singleton Instance { get { if (instance==null) { instance = new Singleton(); } return instance; } } }
Lazy Binding - OK!
Thread safe - NO
如果為了滿足 Thread Safe
public sealed class Singleton { static Singleton instance=null; static readonly object objlock = new object(); Singleton() { } public static Singleton Instance { get { lock (objlock) { if (instance==null) { instance = new Singleton(); } return instance; } } } }
Lazy Binding - OK!
Thread safe - OK!
可惜它有一個很大的缺點 lock 的時間消耗是 if的好幾個數量級
接下來是使用OS中最普遍解法 double checking
if (instance==null) { lock (objlock) { if (instance==null) { instance = new Singleton(); } } } return instance;
當然 其實程式語言也可以很美 利用C#語言的特性
public sealed class Singleton { static readonly Singleton instance = new Singleton(); static Singleton(){} Singleton(){} public static Singleton Instance { get { return instance; } } }
又簡短又正確 可惜它失去Lazy Binding 的能力
想加入Lazy Binding 需要作一些苦工
public sealed class Singleton { Singleton(){} public static Singleton Instance { get { return SingletonPorvider.instance; } } class SingletonPorvider { static SingletonPorvider(){} internal static readonly Singleton instance = new Singleton(); } }
最後 把他泛化
// NON Lazy Binding 版本
public class Singleton<T> where T : new() { private static T instance = new T(); static Singleton(){} Singleton(){} public static T Instance { get { return instance; } } }
// Lazy Binding 版本
public class Singleton<T> where T : new() { Singleton(){} public static T Instance { get { return SingletonPorvider.instance; } } class SingletonPorvider { static SingletonPorvider() { } internal static readonly T instance = new T(); } }