Limita de dimensiune a cozii <T> în .NET?

voturi
50

Am o Queue <T> obiect pe care l-am inițializat la o capacitate de 2, dar, evident, că este doar capacitatea și păstrează în expansiune ca am adăuga elemente. Există deja un obiect care dequeues automat un element atunci când se atinge limita, sau este cea mai bună soluție pentru a crea propria mea clasă moștenit?

Întrebat 04/08/2008 la 15:47
sursa de către utilizator
În alte limbi...                            


7 răspunsuri

voturi
32

Am bătut o versiune de bază a ceea ce caut, nu e perfect, dar va face treaba până când vine împreună ceva mai bun.

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);
    }
}
Publicat 04/08/2008 la 15:57
sursa de către utilizator

voturi
17

Mi - ar recomandăm să trageți în sus Biblioteca C5 . Spre deosebire de SCG (System.Collections.Generic), C5 este programat să interfață și proiectat pentru a fi subclasată. Cele mai multe metode publice sunt virtuale și nici una dintre clase sunt sigilate. În acest fel, nu va trebui să utilizați că scârboasă „nou“ cuvânt cheie care nu ar declanșa în cazul în care dvs. LimitedQueue<T>au fost aruncați într - o SCG.Queue<T>. Cu C5 și folosind aproape același cod ca și ați avut înainte, ar deriva din CircularQueue<T>. CircularQueue<T>Pune efectiv în aplicare atât o stivă și o coadă, astfel încât să puteți obține ambele opțiuni cu o limită de aproape gratuit. L - am rescris de mai jos , cu unele 3.5 constructe:

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();
            }
        }
    }
}

Cred că acest cod ar trebui să facă exact ceea ce cautati.

Publicat 24/10/2008 la 14:51
sursa de către utilizator

voturi
5

Ar trebui să creați propria clasă, un ringbuffer, probabil, s-ar potrivi nevoilor dumneavoastră.

Structurile de date in .NET, care vă permite să specificați capacitate, cu excepția matrice, folosește acest lucru pentru a construi structura de date internă utilizat pentru a păstra datele interne.

De exemplu, pentru o listă, capacitate este utilizată pentru dimensiunea unei matrice interne. Când începeți să adăugați elemente în listă, va începe să umple această matrice din indexul 0 și în sus, iar când ajunge la capacitatea, crește capacitatea de la o nouă capacitate mai mare, și continuă plinu.

Publicat 04/08/2008 la 15:56
sursa de către utilizator

voturi
3

Ei bine Sper că această clasă va ajuta: Pe
plan intern FIFO tamponul circular folosi un Queue <T> cu dimensiunea specificată. Odată ce dimensiunea buffer - ului este atins, acesta va înlocui elemente mai vechi cu altele noi.

NOTĂ: Nu puteți elimina în mod aleatoriu. Am stabilit Eliminați metoda (element T) pentru a reveni fals. Dacă doriți să modificați pentru a elimina elemente aleatoriu

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
}
Publicat 15/11/2011 la 13:40
sursa de către utilizator

voturi
3

De ce n-ai folosi doar o matrice cu o dimensiune de 2? O coadă ar trebui să fie în măsură să crească în mod dinamic și psihiatru.

Sau de a crea o clasă de înveliș în jurul valorii de o instanță de Queue<T>instanță și de fiecare dată când un enqueues un <T>obiect, verificați dimensiunea cozii. În cazul în care mai mult de 2, dequeue primul element.

Publicat 04/08/2008 la 15:52
sursa de către utilizator

voturi
1

Dacă este de folos nimănui, am făcut - o 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; }
    }
}

Acesta elimină cel mai vechi element (partea de jos a stivei), atunci când devine prea mare.

(Această întrebare a fost rezultatul de sus Google pentru „C # dimensiune limită stivă“)

Publicat 15/01/2012 la 06:28
sursa de către utilizator

voturi
0

Soluția de rezolvare simultană

public class LimitedConcurrentQueue<ELEMENT> : ConcurrentQueue<ELEMENT>
{
    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);
        }
    }
}

Notă: Deoarece Enqueuecontrolează adăugarea de elemente, și face acest lucru la un moment dat, nu este nevoie de a executa un whiletimp TryDequeue.

Publicat 09/05/2018 la 20:39
sursa de către utilizator

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more