天天看點

C# 建立單例你會幾種方式?第一種常見的方式建立單例:第二種方式建立單例:第三種方式建立單例:第四種方式建立單例:第五種方式建立單例:

關于為什麼需要建立單例?這裡不過多介紹,具體百度知。

關于C# 建立單例步驟或條件吧

1、聲明靜态變量;2、私有構造函數(無法執行個體化)3、靜态建立執行個體的方法;至于我這裡的Singleton是sealed ,隻是為了防止被繼承,其實有私有構造函數足夠了,這裡隻是為了代碼可讀性。

第一種常見的方式建立單例:

/// 不安全的單例
    /// </summary>
    public sealed class Singleton
    {
        private static Singleton _Singleton;
        private Singleton() { }
        public static Singleton GetSingleton()
        {
            if (_Singleton == null)
            {
                _Singleton = new Singleton();
            }
            return _Singleton;
        }
    }           

注:為什麼說是不安全的單例,多線程通路時可能會new多個對象...

第二種方式建立單例:

/// (多線程)安全單例
    /// </summary>
    public sealed class Singleton
    {
        private static Singleton _Singleton;
        private static readonly object obj = new object();
        private Singleton() { }
        public static Singleton GetSingleton()
        {
            if (_Singleton == null)
            {
                //加鎖保護,在多線程下可以確定執行個體值被建立一次。缺點是每 次擷取單例,都要進行判斷,涉及到的鎖和解鎖比較耗資源。
                lock (obj)
                {
                    if (_Singleton == null)
                    {
                        _Singleton = new Singleton();
                    }
                }

            }
            return _Singleton;
        }
    }           

注:為了解決上面第一種方式建立的不安全執行個體問題應用而生。

第三種方式建立單例:

/// 隻讀單例
    /// </summary>
    public sealed class Singleton
    {
        private static readonly Singleton instance = new Singleton();
        private Singleton() { }
        public static Singleton Instance
        {
            get
            {
                return instance;
            }
        }
    }           
/// 基于上面的隻讀單例=自動屬性隻讀單例(文法糖)
    /// </summary>
    public sealed class Singleton
    {
        private Singleton() { }
        public static Singleton Instance { get; } = new Singleton();
    }           

注:隻讀屬性式=>借助readonly屬性,instance隻被初始化一次,同樣達到了單例的效果。在引用函數執行第一句話之前,instance其實已經被指派了,并不是預期的 隻有到通路Instance變量時才建立對象。

第四種方式建立單例:

/// Singleton中加上靜态構造函數。
    /// </summary>
    public sealed class Singleton
    {
        public static readonly Singleton instance = new Singleton();
        private Singleton()
        {
            Console.WriteLine("初始化1!");
        }
        static Singleton()
        {
        }
        public static Singleton Instance
        {
            get { return instance; }
        }
    }           

注:為了解決(第三種隻讀屬性執行個體)在執行第一句代碼之前,執行個體已經被初始化問題。

第五種方式建立單例:

/// 使用Lazy建立單例,預設是線程安全的
    /// </summary>
    public sealed class Singleton
    {
        private static readonly Lazy<Singleton> instance = new Lazy<Singleton>(() => new Singleton());//
        private Singleton() { }
        public static Singleton Instance
        {
            get
            {
                return instance.Value;
            }
        }
    }           
// 摘要:
        //    初始化System.Lazy`1類的新執行個體。 懶惰初始化時
        //    發生時,使用指定的初始化函數和初始化模式。
     
        // 參數:
        //   valueFactory:
        //   被調用以生成延遲初始化值的委托是必需的參數
        //
        //   isThreadSafe:
        //     如果要使此執行個體可由多個線程同時使用,則為true; false
         //使此執行個體一次隻能由一個線程使用。
        public Lazy(Func<T> valueFactory, bool isThreadSafe);