如何保留最后n个对象的列表?

JYe*_*ton 16 c# collections circular-buffer

我想对特定方法进行一些性能测量,但我想平均完成所需的时间.(这是一个C#Winforms应用程序,但这个问题很适用于其他框架.)

我有一个秒表,我在方法开始时重置并在结束时停止.我想将最后10个值存储在列表或数组中.每个新增加的值都应该从列表中删除最旧的值.

我会定期调用另一种方法来平均所有存储的值.

我认为这个构造是一个循环缓冲区是正确的吗?

如何创建具有最佳性能的缓冲区?现在我有以下内容:

List<long> PerfTimes = new List<long>(10);

// ...

private void DoStuff()
{
    MyStopWatch.Restart();
    // ...
    MyStopWatch.Stop();
    PerfTimes.Add(MyStopWatch.ElapsedMilliseconds);
    if (PerfTimes.Count > 10) PerfTimes.RemoveAt(0);
}
Run Code Online (Sandbox Code Playgroud)

这在某种程度上似乎效率低下,但也许并非如此.

建议?

Tho*_*que 19

您可以创建自定义集合:

class SlidingBuffer<T> : IEnumerable<T>
{
    private readonly Queue<T> _queue;
    private readonly int _maxCount;

    public SlidingBuffer(int maxCount)
    {
        _maxCount = maxCount;
        _queue = new Queue<T>(maxCount);
    }

    public void Add(T item)
    {
        if (_queue.Count == _maxCount)
            _queue.Dequeue();
        _queue.Enqueue(item);
    }

    public IEnumerator<T> GetEnumerator()
    {
        return _queue.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}
Run Code Online (Sandbox Code Playgroud)

您当前的解决方案有效,但效率低,因为删除第一项List<T>是昂贵的.


age*_*t-j 7

private int ct = 0;
private long[] times = new long[10];

void DoStuff ()
{
   ...
   times[ct] = MyStopWatch.ElapsedMilliseconds;
   ct = (ct + 1) % times.Length; // Wrap back around to 0 when we reach the end.
}
Run Code Online (Sandbox Code Playgroud)

这是一个简单的圆形结构.这不需要其他解决方案具有的链表节点的数组复制或垃圾收集.