You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET是否内置可访问最近n个元素的固定长度循环列表?

.NET中维护固定大小的最近元素列表方案

核心结论

目前.NET官方类库没有直接内置这种“固定大小、自动保留最近n个元素、支持访问全部保留元素”的开箱即用结构。

为什么Queue不满足需求

Queue是FIFO结构,虽然可以通过手动限制元素数量实现淘汰旧元素,但它的设计目标是便捷存取首尾元素:

  • 无法直接通过索引访问中间元素,要访问全部元素只能遍历,不符合“随时直观访问全部元素”的需求;
  • 遍历操作可行,但使用体验和效率都不如专门设计的结构。

推荐实现方案

1. 基于List的简单封装(适合大多数场景)

这种实现代码简洁、易于理解,适合元素数量不大、添加频率不高的场景:

public class FixedSizeList<T>
{
    private readonly List<T> _innerList = new List<T>();
    private readonly int _maxCapacity;

    public FixedSizeList(int maxCapacity)
    {
        _maxCapacity = maxCapacity > 0 ? maxCapacity : throw new ArgumentOutOfRangeException(nameof(maxCapacity));
    }

    public void Add(T item)
    {
        _innerList.Add(item);
        if (_innerList.Count > _maxCapacity)
        {
            _innerList.RemoveAt(0);
        }
    }

    // 支持索引访问指定元素
    public T this[int index] => _innerList[index];
    public int Count => _innerList.Count;
    // 返回只读集合,避免外部修改内部列表
    public IReadOnlyList<T> Items => _innerList.AsReadOnly();
}

注意:当元素数量超过_maxCapacity时,RemoveAt(0)是O(n)操作,若n很大且高频添加,会存在性能损耗。

2. 环形数组实现(高性能场景)

如果需要高频添加元素,环形数组实现可以做到O(1)复杂度的添加操作,同时支持索引访问和遍历:

public class CircularBuffer<T>
{
    private readonly T[] _buffer;
    private int _headIndex;
    private int _tailIndex;
    private int _currentCount;

    public CircularBuffer(int capacity)
    {
        if (capacity <= 0)
            throw new ArgumentOutOfRangeException(nameof(capacity));
        _buffer = new T[capacity];
    }

    public void Add(T item)
    {
        _buffer[_tailIndex] = item;
        _tailIndex = (_tailIndex + 1) % _buffer.Length;
        
        if (_currentCount < _buffer.Length)
        {
            _currentCount++;
        }
        else
        {
            _headIndex = (_headIndex + 1) % _buffer.Length;
        }
    }

    // 按添加顺序索引访问元素
    public T this[int index]
    {
        get
        {
            if (index < 0 || index >= _currentCount)
                throw new IndexOutOfRangeException();
            return _buffer[(_headIndex + index) % _buffer.Length];
        }
    }

    public int Count => _currentCount;
    public int Capacity => _buffer.Length;

    // 遍历所有保留的元素(按添加顺序输出)
    public IEnumerable<T> GetOrderedItems()
    {
        for (int i = 0; i < _currentCount; i++)
        {
            yield return this[i];
        }
    }
}

内容的提问来源于stack exchange,提问作者ispiro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 14:36:26