在.NET中限制Queue <T>的大小?

我有一个Queue <T>对象,我已经初始化为2的容量,但显然这只是容量,并且随着我添加项目而不断扩大。 是否已经有一个对象在达到限制时自动出队,或者是创build自己的inheritance类的最佳解决scheme?

我已经敲定了我正在寻找的基本版本,这不是完美的,但它会做的工作,直到有更好的事情来。

public class LimitedQueue<T> : Queue<T> { public int Limit { get; set; } public LimitedQueue(int limit) : base(limit) { Limit = limit; } public new void Enqueue(T item) { while (Count >= Limit) { Dequeue(); } base.Enqueue(item); } } 

我会build议你拉起C5库 。 与SCG(System.Collections.Generic)不同,C5被编程为接口并被devise为子类。 大多数公共方法是虚拟的,没有一个类是封闭的。 这样,你就不必使用这个不好用的“新”关键字,如果你的LimitedQueue<T>被转换为SCG.Queue<T>话,这个关键字不会被触发。 使用C5并使用与之前相同的代码,可以从CircularQueue<T>派生出来。 CircularQueue<T>实际上实现了一个堆栈和一个队列,所以你可以获得几乎免费的限制。 我已经用下面的3.5个结构重写了它:

 using C5; public class LimitedQueue<T> : CircularQueue<T> { public int Limit { get; set; } public LimitedQueue(int limit) : base(limit) { this.Limit = limit; } public override void Push(T item) { CheckLimit(false); base.Push(item); } public override void Enqueue(T item) { CheckLimit(true); base.Enqueue(item); } protected virtual void CheckLimit(bool enqueue) { while (this.Count >= this.Limit) { if (enqueue) { this.Dequeue(); } else { this.Pop(); } } } } 

我认为这个代码应该完全符合你的要求。

你应该创build自己的class级,一个铃声可能会适合你的需要。

.NET中允许指定容量的数据结构(除数组外)使用它来构build用于容纳内部数据的内部数据结构。

例如,对于一个列表,容量用于调整内部数组的大小。 当你开始向列表添加元素时,它将从索引0开始填充这个数组,并且当它到达你的容量时,它将容量增加到一个新的更高的容量,并且继续填充它。

为什么不使用大小为2的数组? 队列应该能够dynamic增长和缩小。

或者在Queue<T>实例的实例周围创build一个包装类,每当一个对象入列一个<T>对象时,检查队列的大小。 如果大于2,则退出第一个项目。

那么我希望这个class会帮助你:
在内部,循环FIFO缓冲区使用指定大小的队列<T>。 一旦达到缓冲区的大小,它将用新的replace旧的项目。

注:您不能随意移除项目。 我将Remove(T item)方法设置为返回false。 如果你想要你可以修改,以随机删除项目

 public class CircularFIFO<T> : ICollection<T> , IDisposable { public Queue<T> CircularBuffer; /// <summary> /// The default initial capacity. /// </summary> private int capacity = 32; /// <summary> /// Gets the actual capacity of the FIFO. /// </summary> public int Capacity { get { return capacity; } } /// <summary> /// Initialize a new instance of FIFO class that is empty and has the default initial capacity. /// </summary> public CircularFIFO() { CircularBuffer = new Queue<T>(); } /// <summary> /// Initialize a new instance of FIFO class that is empty and has the specified initial capacity. /// </summary> /// <param name="size"> Initial capacity of the FIFO. </param> public CircularFIFO(int size) { capacity = size; CircularBuffer = new Queue<T>(capacity); } /// <summary> /// Adds an item to the end of the FIFO. /// </summary> /// <param name="item"> The item to add to the end of the FIFO. </param> public void Add(T item) { if (this.Count >= this.Capacity) Remove(); CircularBuffer.Enqueue(item); } /// <summary> /// Adds array of items to the end of the FIFO. /// </summary> /// <param name="item"> The array of items to add to the end of the FIFO. </param> public void Add(T[] item) { int enqueuedSize = 0; int remainEnqueueSize = this.Capacity - this.Count; for (; (enqueuedSize < item.Length && enqueuedSize < remainEnqueueSize); enqueuedSize++) CircularBuffer.Enqueue(item[enqueuedSize]); if ((item.Length - enqueuedSize) != 0) { Remove((item.Length - enqueuedSize));//remaining item size for (; enqueuedSize < item.Length; enqueuedSize++) CircularBuffer.Enqueue(item[enqueuedSize]); } } /// <summary> /// Removes and Returns an item from the FIFO. /// </summary> /// <returns> Item removed. </returns> public T Remove() { T removedItem = CircularBuffer.Peek(); CircularBuffer.Dequeue(); return removedItem; } /// <summary> /// Removes and Returns the array of items form the FIFO. /// </summary> /// <param name="size"> The size of item to be removed from the FIFO. </param> /// <returns> Removed array of items </returns> public T[] Remove(int size) { if (size > CircularBuffer.Count) size = CircularBuffer.Count; T[] removedItems = new T[size]; for (int i = 0; i < size; i++) { removedItems[i] = CircularBuffer.Peek(); CircularBuffer.Dequeue(); } return removedItems; } /// <summary> /// Returns the item at the beginning of the FIFO with out removing it. /// </summary> /// <returns> Item Peeked. </returns> public T Peek() { return CircularBuffer.Peek(); } /// <summary> /// Returns the array of item at the beginning of the FIFO with out removing it. /// </summary> /// <param name="size"> The size of the array items. </param> /// <returns> Array of peeked items. </returns> public T[] Peek(int size) { T[] arrayItems = new T[CircularBuffer.Count]; CircularBuffer.CopyTo(arrayItems, 0); if (size > CircularBuffer.Count) size = CircularBuffer.Count; T[] peekedItems = new T[size]; Array.Copy(arrayItems, 0, peekedItems, 0, size); return peekedItems; } /// <summary> /// Gets the actual number of items presented in the FIFO. /// </summary> public int Count { get { return CircularBuffer.Count; } } /// <summary> /// Removes all the contents of the FIFO. /// </summary> public void Clear() { CircularBuffer.Clear(); } /// <summary> /// Resets and Initialize the instance of FIFO class that is empty and has the default initial capacity. /// </summary> public void Reset() { Dispose(); CircularBuffer = new Queue<T>(capacity); } #region ICollection<T> Members /// <summary> /// Determines whether an element is in the FIFO. /// </summary> /// <param name="item"> The item to locate in the FIFO. </param> /// <returns></returns> public bool Contains(T item) { return CircularBuffer.Contains(item); } /// <summary> /// Copies the FIFO elements to an existing one-dimensional array. /// </summary> /// <param name="array"> The one-dimensional array that have at list a size of the FIFO </param> /// <param name="arrayIndex"></param> public void CopyTo(T[] array, int arrayIndex) { if (array.Length >= CircularBuffer.Count) CircularBuffer.CopyTo(array, 0); } public bool IsReadOnly { get { return false; } } public bool Remove(T item) { return false; } #endregion #region IEnumerable<T> Members public IEnumerator<T> GetEnumerator() { return CircularBuffer.GetEnumerator(); } #endregion #region IEnumerable Members IEnumerator IEnumerable.GetEnumerator() { return CircularBuffer.GetEnumerator(); } #endregion #region IDisposable Members /// <summary> /// Releases all the resource used by the FIFO. /// </summary> public void Dispose() { CircularBuffer.Clear(); CircularBuffer = null; GC.Collect(); } #endregion } 

如果任何人使用它,我做了一个LimitedStack<T>

 public class LimitedStack<T> { public readonly int Limit; private readonly List<T> _stack; public LimitedStack(int limit = 32) { Limit = limit; _stack = new List<T>(limit); } public void Push(T item) { if (_stack.Count == Limit) _stack.RemoveAt(0); _stack.Add(item); } public T Peek() { return _stack[_stack.Count - 1]; } public void Pop() { _stack.RemoveAt(_stack.Count - 1); } public int Count { get { return _stack.Count; } } } 

当它变得太大时,它将移除最旧的项目(堆栈底部)。

(这个问题是“C#限制堆栈大小”的最高谷歌结果)