Force ConcurrentDictionary in a Singleton Registry to Collect Removed Items/Space I have the following class which is used in a WebApi AspNetCore application as a singleton instance to store Strategy objects (reference type). The class is

/// &lt;summary&gt;
/// Class to allow singleton access to a common thread safe registry of registered strategies.
/// &lt;/summary&gt;
public class StrategyRegister : IStrategyRegister
{
    private ConcurrentDictionary&lt;long, Strategy&gt; _registery;

    public StrategyRegister()
    {
        _registery = new ConcurrentDictionary&lt;long, Strategy&gt;();
    }

    public bool TryAdd(Strategy strategy)
    {
        if (_registery.ContainsKey(strategy.Id))
            throw new SystemException("The registry can never contain two identical strategy ids");
        return _registery.TryAdd(strategy.Id, strategy);
    }

    public bool TryRemove(long id)
    {
        if (!_registery.ContainsKey(id))
            return true;

        //GC.Collect();
        return _registery.TryRemove(id, out _);
    }

    public Strategy TryGet(long id)
    {
        if (_registery.ContainsKey(id))
            return _registery[id];
        return null;
    }

    public IEnumerable&lt;Strategy&gt; GetRegisteredStrategies()
    {
        return _registery.Select(kvp =&gt; kvp.Value);
    }
}


The problem is, as the ConcurrentDictionary grows large and items are removed, they are not being collected by the GC. I confirm this by adding the crude and nasty line GC.Collect() after every removal. When this is done, memory does not grow... I could make this "smarter" (still crude), by adding a timer to force collection every n seconds, but is there a better way, or should I be doing something obvious here?
Apparently, collections are optimized for performance over memory management. So I'm afraid it is up to us, consumers of the .NET Framework, to implement memory management on collections that grow big and require lots of manipulations.

I would use a scheduled task to periodically make a new instance of the queue, with the values of the previous instance, and clearing the old instance.