Begrenzung der Warteschlange <T> in .NET?

  • Ich habe eine Warteschlange & lt; T & gt; Objekt, das ich auf eine Kapazität von 2 initialisiert habe, aber offensichtlich ist dies nur die Kapazität, und es wird immer größer, wenn ich Elemente hinzufüge. Gibt es bereits ein Objekt, das ein Element automatisch ausreißt, wenn das Limit erreicht ist, oder ist die beste Lösung, um eine eigene geerbte Klasse zu erstellen?

    04 August 2008
    tags2k
7 answers
  • Ich habe eine Basisversion von dem, wonach ich suche, erschaffen, es ist nicht perfekt, aber es wird die Arbeit machen, bis etwas Besseres vorkommt.

     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);
        }
    }
     
    19 October 2016
    Espo
  • Ich würde empfehlen, dass Sie die C5 Library aufrufen. Im Gegensatz zu SCG (System.Collections.Generic) ist C5 für die Schnittstelle programmiert und für Unterklassen ausgelegt. Die meisten öffentlichen Methoden sind virtuell und keine der Klassen ist versiegelt. Auf diese Weise müssen Sie nicht dieses icky "neue" Schlüsselwort verwenden, das nicht ausgelöst würde, wenn Ihr LimitedQueue<T> in ein SCG.Queue<T> umgewandelt würde. Bei Verwendung von C5 und Verwendung des gleichen Codes wie zuvor würden Sie von CircularQueue<T> ableiten. Das CircularQueue<T> implementiert tatsächlich sowohl einen Stack als auch eine Queue, sodass Sie beide Optionen mit einem Limit fast kostenlos erhalten können. Ich habe es unten mit einigen 3.5-Konstrukten umgeschrieben:

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

    Ich denke, dass dieser Code genau das tun soll, was Sie tun gesucht haben.

    24 October 2008
    Marcus Griep
  • Sie sollten Ihre eigene Klasse erstellen. Ein Ringpuffer würde wahrscheinlich Ihren Anforderungen entsprechen.

    Die Datenstrukturen in .NET, mit denen Sie die Kapazität angeben können, mit Ausnahme von array verwendet dies, um die interne Datenstruktur aufzubauen, in der die internen Daten gespeichert werden.

    Für eine Liste wird beispielsweise die Kapazität zur Größenbestimmung eines internen Arrays verwendet. Wenn Sie der Liste Elemente hinzufügen, füllt dieses Array ab Index 0 und füllt dieses Array auf. Wenn Ihre Kapazität erreicht ist, wird die Kapazität auf eine neue höhere Kapazität erhöht und das Füllen fortgesetzt.

    04 August 2008
    Lasse Vågsæther Karlsen
  • Warum würden Sie nicht einfach ein Array mit einer Größe von 2 verwenden? Eine Warteschlange soll dynamisch wachsen und schrumpfen können.

    Oder erstellen Sie eine Wrapper-Klasse um eine Instanz von Queue<T> und jedes Mal, wenn ein <T> -Objekt in eine Warteschlange gestellt wird, Überprüfen Sie die Größe der Warteschlange. Falls größer als 2, ziehen Sie das erste Objekt aus der Reihe.

    15 December 2015
    Mr Lister
  • Nun, ich hoffe, diese Klasse wird Ihnen helfen:
    Intern verwenden die Circular FIFO-Puffer eine Warteschlange & lt; T & gt; mit der angegebenen Größe. Sobald die Größe des Puffers erreicht ist, werden ältere Elemente durch neue ersetzt.

    HINWEIS: Sie können Elemente nicht zufällig entfernen. Ich habe die Methode Remove (T item) so eingestellt, dass false zurückgegeben wird. Wenn Sie möchten, können Sie die Elemente zufällig entfernen

    07 February 2016
    Markus SafarMHop
  • Wenn es für jedermann von Nutzen ist, habe ich ein LimitedStack<T> erstellt.

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

    Es entfernt das älteste Element (unterste des Stapels), wenn es zu groß wird.

    (Diese Frage war das Top-Ergebnis von Google für "C # limit stack size")

    15 January 2012
    mpenDDR
  • Gleichzeitige Lösung

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

    Hinweis: Da Enqueue das Hinzufügen der Elemente steuert, und tut dies zu einem Zeitpunkt, es ist nicht erforderlich, while für TryDequeue auszuführen.

    09 May 2018
    SwiftArchitectAleksey Potapov