C# Singleton pattern with triggerable initialization

前端 未结 6 1768
遥遥无期
遥遥无期 2021-02-09 09:45

I need a singleton that:

  • is lazy loaded
  • is thread safe
  • loads some values at construction
  • those values can be queried at any time
6条回答
  •  终归单人心
    2021-02-09 10:09

    Seems like you could do:

    public sealed class Singleton
    {
        IEnumerable Values {get; private set;}
        private Singleton(bool loadDefaults)
        {
            if (loadDefaults)
                Values = new[]{"quick", "brown", "fox"};
            else
                Values = new[]{"another", "set", "of", "values"};
        }
    
        public static Singleton Instance { get { return Nested.instance; } }
    
        public static void Initialize() {
            Nested.Initialize();
        }
    
        private class Nested
        {
            // Explicit static constructor to tell C# compiler
            // not to mark type as beforefieldinit
            static Nested()
            {
            }
    
            internal static readonly Singleton instance = new Singleton(true);
            private static object instanceLock = new object();
            private static bool isInitialized = false; 
    
            public static void Initialize() {
                lock(instanceLock) {
                    if (!isInitialized) {
                        isInitialized = true;
                        instance = new Singleton(false);
                    }
                }
            }
    
        }
    } 
    

    Or to create a single instance that will be updated:

    public sealed class Singleton
    {
        IEnumerable Values {get; private set;}
        private Singleton()
        {
            Values = new[]{"quick", "brown", "fox"};
        }
    
        public static Singleton Instance { get { return Nested.instance; } }
    
        private static object instanceLock = new object();
        private static bool isInitialized = false; 
    
        public static void Initialize() {
            lock(instanceLock) {
                if (!isInitialized) {
                    isInitialized = true;
                    Instance.Values = new[]{"another", "set", "of", "values"};
                }
            }
        }
    
        private class Nested
        {
            // Explicit static constructor to tell C# compiler
            // not to mark type as beforefieldinit
            static Nested()
            {
            }
    
            internal static readonly Singleton instance = new Singleton();
        }
    } 
    

    And the third variation based on your immutable comment and removal of Nested class comment:

    public sealed class Singleton
    {
        IEnumerable Values {get; private set;}
        private Singleton()
        {
            Values = new[]{"quick", "brown", "fox"};
        }
    
        private static Singleton instance;
        private static object instanceLock = new object();
    
        public static Singleton Instance {
            get {
                Initialize();
                return instance;
            }
         }
    
        public static void Initialize() {
            if (instance == null) {
                lock(instanceLock) {
                    if (instance == null)
                        instance = new Singleton();
                }
            }
        }
    } 
    

提交回复
热议问题