rhughes
rhughes

Reputation: 9583

Reusable list which maintains memory

I'm looking for a List<T> type class in .NET which behaves similar to List<T> but doesn't de-allocate its memory when Clear() is called - only resets the Size property.

My aim is to use this class in a memory pool, so I want the memory to be maintained, but have the caller use the class as though it were a standard list, but to avoid lots of memory re-allocations.

If this already exists please let me know as it will save time optimizing, testing and debugging this code.

Here is a mockup of what I'm hoping to find in the .NET library:

public class ReusableList<T>
{
    #region Static Properties

    private static long InitialCapacity = 1000000;
    private static int CapacityIncreaseRate = 10000;

    #endregion

    #region Properties

    public long Size
    {
        get
        {
            return this._size;
        }
        private set
        {
            this._size = 0;
        }
    }
    private long _size = 0;

    private long RealSize
    {
        get
        {
            return this._realSize;
        }
        set
        {
            this._realSize = value;
        }
    }
    private long _realSize = 0;

    private T[] Data
    {
        set
        {
            this._data = value;
        }
        get
        {
            return this._data;
        }
    }
    private T[] _data = null;

    #endregion

    #region Operators

    public T this[long index]
    {
        get
        {
            return this.Data[index];
        }
        set
        {
            this.Data[index] = value;
        }
    }

    #endregion

    #region Public Methods

    public ReusableList()
    {
        this.Rebuild();
    }

    public void Add(T item)
    {
        this.Data[this.Size] = item;

        this._size++;

        if (this.Size >= this.RealSize)
        {
            this.IncreaseSizeOfList();
        }
    }

    public void Clear()
    {
        this.Size = 0;
    }

    #endregion

    #region Private Methods

    private void Rebuild()
    {
        this.Data = null;

        this.Data = new T[ReusableList<T>.InitialCapacity];

        this.Size = 0;

        this.RealSize = ReusableList<T>.InitialCapacity;
    }

    private void IncreaseSizeOfList()
    {
        if (this.Size < this.RealSize)
            return;

        var newData = new T[this.RealSize + ReusableList<T>.CapacityIncreaseRate];

        Array.Copy(this.Data, newData, this.RealSize);

        this.Data = newData;

        this.RealSize += ReusableList<T>.CapacityIncreaseRate;
    }

    #endregion
}

Upvotes: 2

Views: 313

Answers (2)

Dennis
Dennis

Reputation: 37770

As far as I understand, this is default behavior of List<T>.

When you add items to list, it allocates new memory, if needed. When you remove items (or even clear list at all), it neither "frees" memory nor decreases size of internal array.

The only way to decrease internal array is to decrease Capacity. You can look into source code yourself. E.g., here's Clear method:

public void Clear() 
{
    if (_size > 0)
    {
        Array.Clear(_items, 0, _size);
        _size = 0;
    }
    _version++;
}

As you can see, here's only setting array items to defaults and setting size to 0.

Upvotes: 1

Hamid Pourjam
Hamid Pourjam

Reputation: 20754

You can store a backup of internal list.

public class ReusableList<T> : List<T>
{
    private List<T> backup;

    public void Clear(bool purge)
    {
        if (purge)
            backup?.Clear();
        else
            backup = this.ToList();

        base.Clear();
    }

    public new void Clear()
    {
        this.Clear(false);
    }
}

Upvotes: 0

Related Questions