webentwicklung-frage-antwort-db.com.de

Wie überschreibe ich die Add-Methode von List <T> in C #?

Ich bin momentan auf der Suche nach einer eigenen Sammlung, die einer normalen Liste gleicht, außer dass sie nur 10 Artikel enthalten würde. Wenn ein Element hinzugefügt wurde, als bereits 10 Elemente in der Liste vorhanden waren, wurde das erste Element entfernt, bevor das neue Element angehängt wurde.

Was ich tun möchte, ist eine Klasse zu erstellen, die System.Collections.Generic.List<T> erweitert und dann die Add(T item)-Methode dahingehend modifiziert, dass sie die Funktionalität enthält, die ggf. das erste Element entfernt.

33
shinyhappydan

Erstens können Sie Add nicht überschreiben und haben immer noch einen Polymorphismus gegen List . Dies bedeutet, dass Ihre neue Add-Methode nicht aufgerufen wird, wenn Sie das neue Schlüsselwort verwenden und Ihre Klasse als List umgewandelt wird.

Zweitens schlage ich vor, dass Sie in die Queue Klasse schauen, denn was Sie zu tun versuchen, ist eher eine Warteschlange als eine Liste. Die Klasse ist für genau das optimiert, was Sie tun möchten, hat jedoch keinen Größenbegrenzer. 

Wenn Sie wirklich möchten, dass etwas wie eine Liste fungiert, aber wie eine Warteschlange mit einer maximalen Größe arbeitet, sollten Sie IList implementieren und eine Instanz einer Warteschlange zum Speichern Ihrer Elemente beibehalten. 

Zum Beispiel:

public class LimitedQueue<T> : IList<T>
{
  public int MaxSize {get; set;}
  private Queue<T> Items = new Queue<T>();
  public void Add(T item)
  {
    Items.Enqueue(item);
    if(Items.Count == MaxSize)
    {
       Items.Dequeue();
    }
  }
  // I'll let you do the rest
}
41
Randolpho

Sie können die Add-Methode auch über implementieren

public new void Add(...)

in Ihrer abgeleiteten Klasse, um das vorhandene Hinzufügen auszublenden und Ihre Funktionalität einzuführen.

Bearbeiten: Grobe Gliederung ...

class MyHappyList<T> : List<T>
{
    public new void Add(T item)
    {
        if (Count > 9)
        {
            Remove(this[0]);
        }

        base.Add(item);
    }
}

Nur ein Hinweis, es wurde impliziert, aber Sie müssen Ihre benutzerdefinierte Liste immer nach dem tatsächlichen Typ und niemals nach dem Basistyp/der Schnittstelle verweisen, da die Methode zum Ausblenden nur für Ihren Typ und weitere abgeleitete Typen verfügbar ist.

65

Sie können Add () nicht überschreiben, es ist keine virtuelle Methode. Leiten Sie stattdessen von IList ab und verwenden Sie ein privates Mitglied der Warteschlange für die Implementierung.

26
Hans Passant

Sie könnten System.Collections.ObjectModel.Collection erweitern und die InsertItem-Methode überschreiben, um das gewünschte Verhalten zu erhalten. Außerdem wird IList implementiert

17
Lee

Sie können einfach eine Klasse schreiben, die IList<T> implementiert, die einen internen List<T> enthält, und Ihre eigenen Methoden schreiben.

8
Ryan Emerle

Es scheint, als wäre das Beste, was ich tun kann:

class MostRecentList<T> : System.Collections.Generic.List<T> {
        private int capacity;

        public MostRecentList(int capacity) : base() {
            this.capacity = capacity;
        }

        public new void Add(T item) {
            if (base.Count == capacity) {
                base.RemoveAt(0);
            }
            base.Add(item);
        }
}

Da die add()-Methode nicht als virtuell markiert ist.

5
shinyhappydan

Ihre Beschreibung Ihrer Anforderung klingt nach einem Circular Buffer .

Ich habe meine eigene - ähnlich wie diese Implementierung in CodePlex implementiert, mit der Ausnahme, dass meine IList<T> implementiert.

Einige andere Antworten schlagen vor, einen Queue<T> zu verwenden - dies ist jedoch nicht ganz das gleiche, da nur der Zugriff auf FIFO möglich ist.

Generell ist es nicht empfehlenswert, von List<T> abzuleiten - stattdessen von Collection<T> abzuleiten und zusätzliche Elemente zu implementieren, die Sie benötigen. Für einen Umlaufpuffer ist es jedoch wahrscheinlich sinnvoller, ein privates Array zu verwenden, anstatt Collection<T> wie die CodePlex-Implementierung abzuleiten.

3
Joe

Lesen Sie das Liskov-Substitutionsprinzip , Ihre Sammlung ist ein sehr schlechter Kandidat für die Erweiterung von List<T>. Es ist nicht einmal ein großartiger Kandidat für die Implementierung von IList<T>.

Welche Lesemuster sind für diese Daten erforderlich? Wenn Sie nur alle aktuellen Einträge betrachten müssen, reicht es aus, IEnumerable<T> und die Add (T) -Methode zu implementieren.

Dies kann dann durch eine private Warteschlange implementiert werden (oder Deque wäre besser, aber eine solche Sammlung würde einige andere APIs für Sammlungen erfordern, und ich schlage nicht vor, eine zu implementieren), zu der Sie Enqueue () während eines Add (mit Dequeues if) hinzufügen benötigt, um die Größe zu erhalten).

Wenn Sie IEnumerable implementieren und die Add-Methode bereitstellen, können Sie bei Bedarf weiterhin die Collection-Initialisierungssyntax verwenden. 

Wenn Sie einen zufälligen Zugriff auf die Werte benötigen, ist die Implementierung eines Indexers möglicherweise eine gute Idee, aber ich sehe nicht, welchen Nutzen Sie daraus ziehen würden, wenn Sie keinen weiteren Kontext zur Frage hätten.

1
ShuggyCoUk

Sie können sich die Bibliothek der C5-Sammlung ansehen. Sie haben eine ArrayList <T>, die IList <T> implementiert, und eine virtuelle Add-Methode. Die C5-Sammlungsbibliothek ist eine großartige Sammlung von Listen, Warteschlangen, Stapeln usw. Die C5-Bibliothek finden Sie hier:

http://www.itu.dk/research/c5/

1
JohannesH

Sie können versuchen, System.Collections.ObjectModel.Collection<T> zu erweitern, was viel flexibler ist. Sie können dann die geschützten Member InsertItem und SetItem überschreiben, um das Verhalten Ihrer Sammlung anzupassen.

0
bastio84