首页 > 技术文章 > C# 创建单例你会几种方式?

mhg215 2018-10-15 23:41 原文

关于为什么需要创建单例?这里不过多介绍,具体百度知。

  关于C#  创建单例步骤或条件吧

   1、声明静态变量;2、私有构造函数(无法实例化)3、静态创建实例的方法;至于我这里的Singleton是sealed ,只是为了防止被继承,其实有私有构造函数足够了,这里只是为了代码可读性。

  第一种常见的方式创建单例:    

    /// <summary>
    /// 不安全的单例
    /// </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>
    /// (多线程)安全单例
    /// </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>
    /// 只读单例
    /// </summary>
    public sealed class Singleton
    {
        private static readonly Singleton instance = new Singleton();
        private Singleton() { }
        public static Singleton Instance
        {
            get
            {
                return instance;
            }
        }
    }
    /// <summary>
    /// 基于上面的只读单例=自动属性只读单例(语法糖)
    /// </summary>
    public sealed class Singleton
    {
        private Singleton() { }
        public static Singleton Instance { get; } = new Singleton();
    }

:只读属性式=>借助readonly属性,instance只被初始化一次,同样达到了单例的效果。在引用函数执行第一句话之前,instance其实已经被赋值了,并不是预期的 只有到访问Instance变量时才创建对象。

第四种方式创建单例

   
    /// <summary>
    /// 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; }
        }
    }

:为了解决(第三种只读属性实例)在执行第一句代码之前,实例已经被初始化问题。

第五种方式创建单例:

    /// <summary>
    /// 使用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;
            }
        }
    }
// 贴一下关于上面Lazy<T> s=new Lazy<T>()参数的定义;
        // 摘要:
        //    初始化System.Lazy`1类的新实例。 懒惰初始化时
        //    发生时,使用指定的初始化函数和初始化模式。
     
        // 参数:
        //   valueFactory:
        //   被调用以生成延迟初始化值的委托是必需的参数
        //
        //   isThreadSafe:
        //     如果要使此实例可由多个线程同时使用,则为true; false
         //使此实例一次只能由一个线程使用。
        public Lazy(Func<T> valueFactory, bool isThreadSafe);

 

推荐阅读