Vă mulțumim pentru susținere

Dimensiunea limitei de coadă <T> în .NET?

I have a Queue object that I have initialised to a capacity of 2, but obviously that is just the capacity and it keeps expanding as I add items. Is there already an object that automatically dequeues an item when the limit is reached, or is the best solution to create my own inherited class?

0
adăugat

7 răspunsuri

De ce nu ai folosi doar o matrice cu o dimensiune de 2? O coadă ar trebui să fie capabilă să crească și să se micsoreze dinamic.

Or create a wrapper class around an instance of Queue instance and each time one enqueues a object, check the size of the queue. If larger than 2, dequeue the first item.

0
adăugat

Am bătut o versiune de bază a ceea ce caut, nu este perfectă, dar va face treaba până va veni ceva mai bun.

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);
    }
}
0
adăugat
O apreciere bună privind schimbarea codului "setter" pentru proprietatea "Limit".
adăugat autor Pure.Krome
Există o limitare foarte gravă pentru această clasă, pe care Marcus Griep la sugerat în răspunsul său: deoarece metoda Enqueue este declarată ca new (deoarece Queue . Enquee nu este virtuală), dacă cineva îți aruncă LimitedQueue într-o coadă doriți fără ca limita dvs. să aibă efect. Aș recomanda de asemenea schimbarea dacă (this.Count> = this.Limit) în în timp ce (this.Count> = this.Limit) (pentru scenariul pe care tocmai l-am menționat, de exemplu).
adăugat autor Dan Tao
Dacă celelalte metode ale Coadă apelează Enqueue (), inițiativele Enqueue vor fi chemați și pot cauza o problemă gravă
adăugat autor Louis Rhys
Am mărit ușor codul cu un apel din cadrul proprietății Set de limită care asigură că mărimea cozii nu a depășit limita - doar o simplă În timp ce este mai mare decât Limit, Dequeue. În afară de asta, aceasta este o soluție excelentă, asta-i frumos și simplu, mulțumesc.
adăugat autor Scott

Ar trebui să vă creați propria clasă, un ringbuffer ar fi probabil potrivit nevoilor dumneavoastră.

Structurile de date din .NET care vă permit să specificați capacitatea, cu excepția matricei, utilizează acest lucru pentru a construi structura internă de date utilizată pentru a ține datele interne.

De exemplu, pentru o listă, capacitatea este folosită pentru a dimensiona o matrice internă. Când începeți să adăugați elemente în listă, va începe să umpleți acest matrice din indexul 0 și în sus și când atinge capacitatea dvs., crește capacitatea la o capacitate mai mare și continuă să o umpleți.

0
adăugat

If it's of any use to anyone, I made a 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; }
    }
}

Îndepărtează cel mai vechi element (partea de jos a stivei) când devine prea mare.

(Această întrebare a reprezentat cel mai bun rezultat Google pentru "mărimea stackului limită C #")

0
adăugat
Acest cod este 99% corect. Cu toate acestea, dacă numim Peek sau Pop fără a pune nimic pe stivă, acesta se va prăbuși deoarece indicele este -1. Acest lucru ar putea fi ușor de stabilit prin adăugarea de verificarea limitelor indexului.
adăugat autor Contango
Sugerați adăugarea următorilor parametri la Peek and Pop (): if ((_stack.Count - 1) <0) aruncați o nouă excepție ("Can not Peek or Pop fără a face o apăsare.") ;. Acest lucru ar alerta programatorul la acest caz colț, și să le permită să-l păstrați în minte atunci când utilizați această clasă. Am putea adăuga, de asemenea, un TryPeek sau TryPop, care este abordarea pe care Microsoft a făcut-o cu implementările lor ConcurrentDictionary.
adăugat autor Contango
Pentru înregistrare, acest cod nu este sigur în siguranță, fără blocare suplimentară (ceea ce este absolut sigur, siguranța filetului nu a făcut niciodată parte din specificațiile de design pentru această clasă).
adăugat autor Contango

Soluție concurentă

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

Notă: Deoarece Enqueue controlează adăugarea de elemente și o face una câte una, nu este nevoie să executați un în timp ce pentru TryDequeue .

0
adăugat

I would recommend that you pull up the C5 Library. Unlike SCG (System.Collections.Generic), C5 is programmed to interface and designed to be subclassed. Most public methods are virtual and none of the classes are sealed. This way, you won't have to use that icky "new" keyword which wouldn't trigger if your LimitedQueue were cast to a SCG.Queue. With C5 and using close to the same code as you had before, you would derive from the CircularQueue. The CircularQueue actually implements both a stack and a queue, so you can get both options with a limit nearly for free. I've rewritten it below with some 3.5 constructs:

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

Cred că acest cod ar trebui să facă exact ceea ce căutați.

0
adăugat

Well I hope this class will helps You:
Internally the Circular FIFO Buffer use a Queue with the specified size. Once the size of the buffer is reached, it will replaces older items with new ones.

NOTĂ: Nu puteți să ștergeți articole aleatoriu. Am setat metoda Remove (item T) pentru a reveni false. dacă doriți Puteți modifica pentru a elimina articolele în mod aleatoriu

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
}
0
adăugat
Cred că prin utilizarea acestui cod puteți avea o coadă de dimensiuni limitate .. care este, de asemenea, tampon Circular.
adăugat autor Robel.E