J'ai un objet Queue <T> que j'ai initialisé avec une capacité de 2, mais il ne s'agit évidemment que de la capacité et il continue de s'étendre à mesure que j'ajoute des éléments. Existe-t-il déjà un objet qui met automatiquement en file d'attente un élément lorsque la limite est atteinte, ou est-ce la meilleure solution pour créer ma propre classe héritée?
Réponses
Trop de publicités?Je recommanderais que vous tirez vers le haut la C5 de la Bibliothèque. Contrairement à la CTB (Système d'.Les Collections.Générique), la C5 est programmé pour l'interface et conçu pour être sous-classé. La plupart des méthodes sont virtuelles et aucune des classes sont scellés. De cette façon, vous n'aurez pas à utiliser de dégueulasse "nouveau" mot clé qui ne se déclenche pas si votre LimitedQueue<T>
ont été convertis en SCG.Queue<T>
. Avec C5 et en utilisant à peu près le même code que vous aviez avant, vous dériverait de l' CircularQueue<T>
. L' CircularQueue<T>
fait implémente à la fois une pile et une file d'attente, de sorte que vous pouvez obtenir à la fois des options avec une limite de près de pour gratuit. J'ai réécrit il ci-dessous avec quelques 3.5 constructions:
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();
}
}
}
}
Je pense que ce code doit faire exactement ce que vous cherchez.
J'espère que ce cours vous aidera:
En interne, le tampon circulaire FIFO utilise une file d'attente <T> avec la taille spécifiée. Une fois la taille de la mémoire tampon atteinte, les éléments les plus anciens seront remplacés par de nouveaux.
REMARQUE: vous ne pouvez pas supprimer d’éléments de manière aléatoire. J'ai défini la méthode Remove (T item) sur false. si vous voulez, vous pouvez modifier pour supprimer des éléments au hasard
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
}
Vous devez créer votre propre classe, un ringbuffer serait probablement s'adapter à vos besoins.
Les structures de données .NET qui vous permet de spécifier la capacité, à l'exception de tableau, l'utilise pour construire la structure de données interne utilisé pour contenir les données internes.
Par exemple, pour une liste, la capacité est utilisée pour la taille d'une batterie interne. Lorsque vous commencez à ajouter des éléments à la liste, il va commencer à remplir ce tableau à partir de l'indice 0 et en haut, et quand il atteint votre capacité, il augmente la capacité de un nouveau de plus grande capacité, et continue à le remplir.
Pourquoi ne pas simplement utiliser un tableau de taille 2? Une file d'attente est supposée pouvoir se développer et se réduire de manière dynamique.
Ou créez une classe wrapper autour d'une instance d'instance de file d'attente et chaque fois que vous mettez un objet en file d'attente, vérifiez la taille de la file d'attente. Si supérieur à 2, retirez le premier élément de la file d'attente.