.NET Queue'ya <T> sınırı boyutu?

oy
50

Ben 2 'lik bir kapasiteye başlatıldı gelmiş bir Kuyruk <T> nesne var, ama belli ki bu sadece kapasite ve ben öğeler eklemek gibi genişleyen devam ediyor. sınıra ulaşıldığında otomatik olarak veya kendi kalıtsal sınıf oluşturmak için en iyi çözümdür zaman bir öğe dequeues bir nesne zaten var mıdır?

Oluştur 04/08/2008 saat 15:47
kaynak kullanıcı
Diğer dillerde...                            


7 cevaplar

oy
32

Ben aradığım temel bir sürümünü hamile ettik mükemmel değil ama daha iyi bir şey bulana o işi yapacağız.

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);
    }
}
Cevap 04/08/2008 saat 15:57
kaynak kullanıcı

oy
17

Sana yukarı çekin öneririm C5 Kütüphanesi . SCG (System.Collections.Generic) farklı olarak, C5 arayüzüne programlanır ve sınıflandırma için tasarlanmıştır. Çoğu kamu sanal yöntemlerdir ve sınıfların hiçbiri mühürlü. Bu şekilde, eğer senin tetiklemek olmaz iğrenç "yeni" anahtar kelime kullanmak zorunda kalmazsınız LimitedQueue<T>bir artığını edildi SCG.Queue<T>. C5 ve daha önce olduğu gibi aynı koda yakın kullanılarak sayesinde, elde edilebilecek CircularQueue<T>. CircularQueue<T>Neredeyse ücretsiz bir limitli iki seçeneği alabilirsiniz aslında bir yığın ve kuyruk hem uygular. Bazı 3,5 yapıları ile altına yeniden kaleme aldık:

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

Bu kod aradığınız tam olarak ne yapması gerektiğini düşünüyorum.

Cevap 24/10/2008 saat 14:51
kaynak kullanıcı

oy
5

Bir Ringbuffer muhtemelen ihtiyaçlarınızı uyabilecek, kendi sınıf oluşturmak gerekir.

Eğer dizinin haricinde kapasite belirlemenizi sağlar .NET veri yapıları, iç verileri tutmak için kullanılan iç veri yapısını oluşturmak için bunu kullanır.

Örneğin, bir liste için, kapasite boyutuna bir iç dizi kullanılır. Listeye unsurları ekleyerek başlattığınızda, endeks 0 ve üstü bu dizi dolum başlayacağız ve bu kapasitenizi ulaştığında, yeni bir yüksek kapasite kapasiteyi artırır ve onu dolduruyor devam ediyor.

Cevap 04/08/2008 saat 15:56
kaynak kullanıcı

oy
3

Eh ben bu sınıf irade You yardımcı olur umarım:
Dahili olarak Dairesel FIFO Tampon belirtilen boyutta bir Kuyruk <T> kullanın. Tampon boyutu ulaşıldığında, bu yenileriyle eski öğeleri değiştirir olacaktır.

NOT: rastgele öğeleri kaldıramazsınız. Ben yanlış dönmek için yöntem Kaldır (T öğesi) olarak ayarlayın. Sen istersen rastgele öğeleri kaldırmak için değiştirebilir

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
}
Cevap 15/11/2011 saat 13:40
kaynak kullanıcı

oy
3

Neden sadece 2 boyutunda bir dizi kullanmak ister? Bir Kuyruk dinamik büyümeye ve küçültmek mümkün olması gerekiyordu.

Veya bir örneği etrafında sarıcı sınıf oluşturmak Queue<T>örneği ve her zaman bir enqueues bir <T>nesne sırasının boyutunu kontrol edin. Daha büyük 2 ise ilk öğeyi sıradan çıkarma.

Cevap 04/08/2008 saat 15:52
kaynak kullanıcı

oy
1

O kimseye herhangi bir kullanım varsa, ben bir yapılan 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; }
    }
}

O çok büyük olur en eski öğeyi (yığının alt) kaldırır.

(Bu soru "C # sınırı yığın boyutu" için en iyi Google sonucuydu)

Cevap 15/01/2012 saat 06:28
kaynak kullanıcı

oy
0

Eşzamanlı Çözüm

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: bu yana Enqueueelemanların kontrolleri eklenmesi, ve bir seferde bu kadar birini yapar, bir yürütmek için gerek yoktur whileiçin TryDequeue.

Cevap 09/05/2018 saat 20:39
kaynak kullanıcı

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