¿Limitar el tamaño de Queue en .NET?

Tengo un objeto Queue que he inicializado a una capacidad de 2, pero obviamente esa es solo la capacidad y sigue expandiéndose a medida que agrego elementos. ¿Ya hay un objeto que dequeue automáticamente un artículo cuando se alcanza el límite, o es la mejor solución para crear mi propia clase heredada?

He alterado una versión básica de lo que estoy buscando, no es perfecta, pero hará el trabajo hasta que surja algo mejor.

public class LimitedQueue : Queue { 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); } } 

Recomiendo que levante la Biblioteca C5 . A diferencia de SCG (System.Collections.Generic), C5 está progtwigdo para interfaz y diseñado para ser subclassed. La mayoría de los métodos públicos son virtuales y ninguna de las clases está sellada. De esta forma, no tendrá que usar esa palabra clave icky “nueva” que no se LimitedQueue si su LimitedQueue se SCG.Queue en SCG.Queue . Con C5 y usando casi el mismo código que tenía antes, derivaría de la CircularQueue . La CircularQueue realidad implementa tanto una stack como una cola, por lo que puede obtener ambas opciones con un límite casi gratuito. Lo he reescrito a continuación con unos 3.5 constructos:

 using C5; public class LimitedQueue : CircularQueue { 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(); } } } } 

Creo que este código debería hacer exactamente lo que estabas buscando.

Debes crear tu propia clase, un Ringbuffer probablemente se ajuste a tus necesidades.

Las estructuras de datos en .NET que le permiten especificar la capacidad, a excepción de la matriz, usa esto para construir la estructura de datos interna utilizada para contener los datos internos.

Por ejemplo, para una lista, la capacidad se usa para dimensionar una matriz interna. Cuando comience a agregar elementos a la lista, comenzará a llenar esta matriz desde el índice 0 y hacia arriba, y cuando scope su capacidad, boostá la capacidad a una nueva capacidad más alta y continuará llenándola.

¿Por qué no usarías simplemente una matriz con un tamaño de 2? Se supone que una cola puede crecer y contraerse dinámicamente.

O cree una clase contenedora alrededor de una instancia de la instancia Queue y cada vez que uno encola un objeto , verifique el tamaño de la cola. Si es mayor que 2, dequeue el primer elemento.

Bueno, espero que esta clase te ayude:
Internamente, el búfer FIFO circular utiliza una cola con el tamaño especificado. Una vez que se alcanza el tamaño del búfer, reemplazará los artículos más viejos por otros nuevos.

NOTA: no puede eliminar elementos al azar. Configuro el método Eliminar (elemento T) para devolver falso. si lo desea, puede modificar para eliminar elementos al azar

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

Si sirve para cualquiera, hice una LimitedStack .

 public class LimitedStack { public readonly int Limit; private readonly List _stack; public LimitedStack(int limit = 32) { Limit = limit; _stack = new List(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; } } } 

Quita el elemento más antiguo (parte inferior de la stack) cuando se vuelve demasiado grande.

(Esta pregunta fue el resultado principal de Google para “tamaño de stack límite de C #”)

Solución concurrente

 public class LimitedConcurrentQueue : ConcurrentQueue { public readonly int Limit; public LimitedConcurrentQueue(int limit) { Limit = limit; } public new void Enqueue(ELEMENT element) { base.Enqueue(element); if (Count > Limit) { TryDequeue(out ELEMENT discard); } } } 

Nota: Como Enqueue controla la adición de elementos, y lo hace de uno en uno, no es necesario ejecutar un while para TryDequeue .