要用于最后操作的循环列表的集合

本文关键字:循环 集合 列表 操作 用于 最后 | 更新日期: 2023-09-27 18:00:31

我正在寻找一种允许我定义最大容量的C#集合类型。我想将对象添加到此集合中,当我的容量达到时,最旧的对象应该被新的对象替换。

具体来说,我想创建一个集合来记忆我最近的10或20个动作。

我已经阅读了谷歌上的文章,但我正在从这个社区寻找答案。

要用于最后操作的循环列表的集合

.NET中唯一固定的集合类型是数组,因此它是唯一满足您需求的集合类型。

你可以保留一个索引来进行旋转。你只需要记住你下一个要写的位置是什么。

类似这样的东西:

int index = 0;
string[] collection = new string[10];
public void Write(string text)
{
    index %= collection.Length; // prevent overflowing
    collection[index++] = text;
}

如果您的应用程序对性能不敏感,那么您可以使用通用集合Queue
以下是可以解决您问题的包装器示例:

public class LimitedQueue<T>
{
    private readonly Queue<T> _queue;
    private readonly int _limit;
    public LimitedQueue(int limit)
    {
        _queue = new Queue<T>();
        _limit = limit;
    }
    public void Enqueue(T item)
    {
        if (_queue.Count == _limit) _queue.Dequeue();
        _queue.Enqueue(item);
    }
    public T Dequeue()
    {
        return _queue.Dequeue();
    }
    public T Peek()
    {
        return _queue.Peek();
    }
    public T[] GetAll()
    {
        return _queue.ToArray();
    }
}

它的性能不如数组,但它可以让您做一些有用的事情,比如从Queue获取所有项。

您所描述的类型我一直称之为FixedQueue或固定大小FIFO。这个想法是先入先出,但如果超过大小,则丢弃先出:

public class FixedQueue<T>
{
    private readonly ConcurrentQueue<T> _innerQueue;
    private int _length;
    public FixedQueue(int length)
    {
        _length = length;
        _innerQueue = new ConcurrentQueue<T>(length);
    }  
    public void Enqueue(T obj)
    {
        lock (_innerQueue)
        {
            if (_innerQueue.Length == _length)
                _innerQueue.Dequeue();
            _innerQueue.Enqueue(obj);
        }
    }
    public T Dequeue()
    {
        lock (_innerQueue)
        {
            return _innerQueue.Dequeue();
        }
    }
    // etc...
}

如果您正在寻找一个具有继承性的更面向对象的解决方案,并且不关心维护,那么您可以编写以下内容:

public class FixedQueue<T> : Queue<T>
{
    //private readonly ConcurrentQueue<T> _innerQueue;
    private int _capacity;
    public FixedQueue(int capacity) : base()
    {
        _capacity = capacity;
    }
    public void Enqueue(T obj)
    {
        lock(this)
        {
            if (this.Count == _capacity)
                base.Dequeue();
            base.Enqueue(obj);
        }
    }
    public T Dequeue()
    {
        lock (this)
        {
            return this.Dequeue();
        }
    }
}

这个解决方案不尊重新趋势,即您应该更喜欢组合而不是继承。