Search code examples
c#garbage-collectionsingletonidisposable

How to dispose/garbage collect a singleton instance


I am using a Singleton instance created out of a nested class. This instance holds some static collections which are cleared when the Singleton is disposed, but the problem is I get a reference to non-null disposed Singleton which is not properly garbage collected.

I would like to know how to completely dispose and garbage collect my Singleton instance so that when the instance is queried again after dispose (and setting to null) a new Instance is created.

I am using the following nested pattern for Singleton instance:

public class SingletonClass : IDisposable
{
    private List<string> _collection;

    private SingletonClass()
    {
    }

    public static SingletonClass Instance
    {
        get
        {
            return Nested.Instance; //line 1 - this line returns the non-null instance after dispose and setting the Singleton instance to null which is causing problems
        }
    }

    private void Init()
    {
        _collection = new List<string>();
        //Add data to above collection
    }

    public void Dispose()
    {
        //Release collection
        _collection.Clear();
        _collection = null;
    }

    class Nested
    {
        static Nested()
        {
            Instance = new SingletonClass();
            Instance.Init();
        }
    
        internal static readonly SingletonClass Instance;
    }    
}

The problem at line 1 is that after dispose of SingletonClass from client class, the _collection object becomes null while the SingletonClass instance remains non-null even after setting = null.


Solution

  • You'll only need to implement System.IDisposable if you fulfill following basic requirement:

    The primary use of this interface is to release unmanaged resources.

    Then I would go for the destructor of the class and call Dispose() in the Microsoft Docs Example.

    Otherwise

    The garbage collector automatically releases the memory allocated to a managed object when that object is no longer used.

    (which won't be the case with a real singleton, unless the process ends)

    You may be better off, if you are using sth like this

    class PseudoSingleton<T>
        where T : new()
    {
        private readonly object _lock = new object();
        private T _instance;
    
        public T Instance
        {
            get
            {
                lock (this._lock)
                {
                    if (this._instance != null)
                    {
                        this._instance = new T();
                    }
                    return this._instance;
                }
            }
        }
        public void Reset()
        {
            lock (this._lock)
            {
                this._instance = null;
            }
        }
    }