Generic Object Pool in C# I have a limit of 100 sessions (each session held in an object). Many threads will be requesting sessions, and it is very possible that all 100 sessions could be in use at any time.

I'm a Junior Developer. I saw the Object Pool pattern and decided that it looked appropriate. What do you think? If no sessions are avaible, the thread that requested it will get an Exception back and have to try again.

I'm using IOC with ISessionPool as a singleton. In testing it seems to work well, but I'd appreciate any feedback.

public class SessionPool&lt;T&gt; : ISessionPool&lt;T&gt;
{
    private readonly List&lt;T&gt; _inUse;
    private readonly List&lt;T&gt; _available;
    private readonly Action&lt;T&gt; _cleanerAction;

    /// &lt;summary&gt;
    /// Creates an object pool for objects of type T.
    /// NOTE: All availbale instances are initialised immediately.
    /// &lt;/summary&gt;
    /// &lt;param name="instanceCreator"&gt;A function that creates objects of type T&lt;/param&gt;
    /// &lt;param name="maxInstances"&gt;The maximum number of instances&lt;/param&gt;
    /// &lt;param name="cleanerAction"&gt;An action that cleans up the object before it is returned to the pool&lt;/param&gt;
    public SessionPool(Func&lt;T&gt; instanceCreator, int maxInstances, Action&lt;T&gt; cleanerAction)
    {
        _inUse = new List&lt;T&gt;(maxInstances);
        _available = new List&lt;T&gt;(maxInstances);
        _cleanerAction = cleanerAction;

        CreateAllInstances(instanceCreator, maxInstances);
    }

    private void CreateAllInstances(Func&lt;T&gt; instanceCreator, int numberOfInstances)
    {
        for (int i = 0; i &lt; numberOfInstances; i++)
        {
            _available.Add(instanceCreator.Invoke());
        }
    }

    public T GetSession()
    {
        lock (_available)
        {
            if (_available.Count == 0)
            {
                throw new NoAvailableSessionsException("Unable to get session");
            }
            else
            {
                T toReturn = _available[0];
                _inUse.Add(toReturn);
                _available.RemoveAt(0);
                return toReturn;
            }
        }
    }

    public void ReleaseSession(T session)
    {
        // Clean up the object before making it available again
        _cleanerAction.Invoke(session);

        lock (_available)
        {
            _available.Add(session);
            _inUse.Remove(session);
        }
    }

    public int GetAvailableSessionCount()
    {
        lock (_available)
        {
            return _available.Count;
        }
    }
}
A security problem is ReleaseSession adds whatever T session passed to _available, whether it was issued by you or not.

You can change _inUse like so:

HashSet _inUse = new HashSet&lt;T&gt;(new ObjectReferenceEqualityComparer&lt;T&gt;())


where ObjectReferenceEqualityComparer is an EqualityComparer that uses Object.ReferenceEquals and check whether _inUse contains session before adding it to the _available to avoid that problem.

You may think because you intend, for now, to use this pool with class X, which you think, for now, this problem does not apply. It may turn out that this problem applies to X after all, or someone else, or even yourself, may use this pool for some other class Y.