An obvious singleton implementation for .NET?

后端 未结 7 1113
轻奢々
轻奢々 2020-12-02 11:38

I was thinking about the classic issue of lazy singleton initialization - the whole matter of the inefficiency of:

if (instance == null)
{
    instance = new         


        
相关标签:
7条回答
  • 2020-12-02 12:01

    This is the canonical, thread safe, lazy Singleton pattern in C#:

    public sealed class Singleton
    {
        Singleton(){}
        public static Singleton Instance
        {
            get
            {
                return Nested.instance;
            }
        }        
        class Nested
        {
            // Explicit static constructor to tell C# compiler
            // not to mark type as beforefieldinit
            static Nested() {}    
            internal static readonly Singleton instance = new Singleton();
        }
    }
    
    0 讨论(0)
  • 2020-12-02 12:07

    I always use this regular (non-lazy) one (you could nest it like the other examples): (requires using System.Reflection;)

    public class SingletonBase<T> where T : class
    {
        static SingletonBase()
        {
        }
    
        public static readonly T Instance = 
            typeof(T).InvokeMember(typeof(T).Name, 
                                    BindingFlags.CreateInstance | 
                                    BindingFlags.Instance |
                                    BindingFlags.Public |
                                    BindingFlags.NonPublic, 
                                    null, null, null) as T;
    }
    
    0 讨论(0)
  • 2020-12-02 12:09

    Have you measured the performance?

    Do you believe that an additional function call is cheaper than an if?

    I agree with the others that using the static ctor works well for this initialization. This will also get rid of the inherent race condition that the you have since .net guarentees that static constructors will only be called once.

    0 讨论(0)
  • 2020-12-02 12:13

    the whole matter of the inefficiency of:...

    What inefficiency?

    Those instructions will result into an extremely fast fragments of assembly code. I am completely sure that there is nothing to be gained by trying to "optimize" this. Even if you come up with something faster, it will be at a significant complexity cost.

    Unless you do have positive evidence that this code is affecting your performance, you should use the simplest approach that solves your problem.

    0 讨论(0)
  • 2020-12-02 12:27

    To prevent from having to copy the singleton code, you could make the type generic, as such:

    public abstract class Singleton<T>
        where T: class, new()
    {
        public static T Instance
        {
            get { return Nested.instance; }
        }
    
        private class Nested
        {
            // Explicit static constructor to tell C# compiler
            // not to mark type as beforefieldinit
            static Nested() { }
    
            internal static readonly T instance = new T();
        }
    }
    
    public sealed class MyType : Singleton<MyType>
    {
    }
    
    class Program
    {
        static void Main()
        {
            // two usage pattterns are possible:
            Console.WriteLine(
                ReferenceEquals(
                    Singleton<MyType>.Instance, 
                    MyType.Instance
                )
            );
            Console.ReadLine();
        }
    }
    
    0 讨论(0)
  • 2020-12-02 12:27

    The best method I have found of creating a singleton is this:

    public class Singleton
    {
        static public Singleton Instance { get; } = new Singleton();
        private Singleton() { ... }
    }
    

    It is very concise, and more importantly, is also thread safe, which can be very troublesome to detect and fix as an application matures.


    Update: To show it is lazy...

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace SingletonTest
    {
        class MySingleton
        {
            static public MySingleton Instance { get; } = new MySingleton();
    
            private MySingleton() { Console.WriteLine("Created MySingleton"); }
    
            public void DoSomething() { Console.WriteLine("DoSomething"); }
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("Starting Main");
    
                MySingleton.Instance.DoSomething();
            }
        }
    }
    

    Output:

    Starting Main
    Created MySingleton
    DoSomething
    
    0 讨论(0)
提交回复
热议问题