Warum nicht von List & lt; T & gt;

Bei der Planung meine Programme, die ich starten oft mit einer Kette von Gedanken wie:

Einer Fußball-Mannschaft ist nur eine Liste der Fußball-Spieler. Also, ich soll es mit:

var football_team = new List<FootballPlayer>();

Die Bestellung von dieser Liste repräsentieren die Reihenfolge, in der die Spieler aufgeführt sind, die in den Dienstplan.

Aber ich merke später, dass die teams haben auch andere Eigenschaften, neben der reinen Liste der Spieler, die festgehalten werden müssen. Zum Beispiel, die laufende Summe erzielt in dieser Saison, das aktuelle budget, die uniform-Farben, ein string für den Namen der Mannschaft, etc..

Also dann denke ich:

Okay, ein Fußball-team ist ebenso wie eine Liste von Spielern, sondern zusätzlich, es hat einen Namen (eine string) und eine laufende Summe der scores (ein int). .NET nicht eine Klasse für die Speicherung von Fußball-teams, also werde ich meine eigene Klasse. Die meisten ähnlichen und relevanten vorhandenen Struktur List<FootballPlayer>, so werde ich von Ihr Erben:

class FootballTeam : List<FootballPlayer> 
{ 
    public string TeamName; 
    public int RunningTotal 
}

Aber es stellt sich heraus, dass eine Richtlinie sagt, man sollte nicht die Erben von List<T>. Ich bin gründlich verwirrt durch diese Richtlinie in zweifacher Hinsicht.

Warum nicht?

Offenbar List ist irgendwie für die Leistung optimiert. Wie so? Was performance-Probleme werde ich veranlassen, wenn ich verlängern List? Was genau wird kaputt?

Einem anderen Grund, den ich gesehen habe, ist, dass List von Microsoft bereitgestellt wird, und ich habe keine Kontrolle über Sie, so Ich kann es nicht ändern später, nachdem man eine "public API". Aber ich kämpfen, um das zu verstehen. Was ist eine öffentliche API und warum sollte mich das interessieren? Wenn mein Aktuelles Projekt nicht und ist wahrscheinlich nicht immer haben diese öffentliche API, die kann ich ignorieren diese Richtlinie? Wenn ich Erben von List und es stellt sich heraus, ich brauche eine öffentliche API, welche Schwierigkeiten habe ich?

Warum ist es auch egal? Eine Liste ist eine Liste. Was könnte sich ändern? Was könnte ich vielleicht ändern wollen?

Und schließlich, wenn Microsoft wollte mich nicht Erben aus List, warum haben Sie nicht machen die Klasse sealed?

Was soll ich verwenden?

Offenbar für eine benutzerdefinierte Sammlungen, die Microsoft bereitgestellt hat, eine Collection - Klasse, die erweitert werden soll, anstatt List. Aber diese Klasse ist sehr nüchtern, und nicht haben viele nützliche Dinge, wie AddRange, zum Beispiel. jvitor83 Antwort bietet eine Leistung Begründung für die jeweilige Methode, aber wie ist ein langsamer AddRange nicht besser als gar keine AddRange?

Erben von Collection ist viel mehr Arbeit, als Erben von List, und ich sehe keinen Vorteil. Sicherlich Microsoft würde nicht sagen Sie mir, um zusätzliche Arbeit zu tun, ohne Grund, so kann ich nicht helfen Gefühl, wie ich bin irgendwie Missverständnis etwas, und Erben Collection ist eigentlich nicht die richtige Lösung für mein problem.

Ich gesehen habe Vorschläge, wie die Umsetzung IList. Nur kein. Dies ist Dutzende von Zeilen boilerplate-code, die Gewinne mir nichts.

Schließlich, einige schlagen vor, das einwickeln der List in etwas:

class FootballTeam 
{ 
    public List<FootballPlayer> Players; 
}

Gibt es zwei Probleme:

  1. Macht es mein code unnötig ausführlich. Ich muss jetzt anrufen my_team.Players.Count statt nur my_team.Count. Zum Glück, mit C# kann ich definieren, Indexer, um die Indizierung transparent, und uns alle die Methoden des internen List... Aber das ist eine ganze Menge code! Was bekomme ich für alle, dass die Arbeit?
  2. Einfach keinen Sinn. Eine Fußball-Mannschaft nicht "haben" eine Liste der Spieler. Es ist die Liste der Spieler. Sagen Sie nicht: "John McFootballer hat sich SomeTeam Spieler". Sie sagen: "John hat sich SomeTeam". Sie don T fügen Sie einen Brief an "einen string s Zeichen", fügen Sie einen Buchstaben in einen string. Sie don ' T fügen Sie ein Buch zu einer Bibliothek, die Bücher, die Sie hinzufügen, ein Buch zu einer Bibliothek.

Merke ich, dass was passiert "unter der Haube" kann gesagt werden, "hinzufügen von X zu Y die interne Liste", aber dies scheint wie eine sehr counter-intuitive Art und Weise des Denkens über die Welt.

Meine Frage (zusammengefasst)

Was ist die richtige C# Möglichkeit der Darstellung einer Datenstruktur, die "logisch" ist (das heißt, "den menschlichen Geist") ist nur ein list von things mit ein paar Glocken und Pfeifen?

Erbt von List<T> immer inakzeptabel? Wann ist es akzeptabel? Warum/warum nicht? Was muss ein Programmierer betrachten, bei der Entscheidung, ob Erben von List<T> oder nicht?

Kommentar zu dem Problem
Also, Ihre Frage ist wirklich, Wann die Vererbung verwenden (ein Quadrat ist ein Rechteck, weil es ist immer sinnvoll, bieten ein Quadrat, wenn eine generische Rechteck angefordert wurde) und Wann verwendet man Komposition (ein FootballTeam hat-eine Liste von FootballPlayers, zusätzlich zu anderen Eigenschaften, die nur als "grundlegend", wie ein name)? Würde andere Programmierer verwechselt werden, wenn an anderer Stelle im code, die Sie übergeben Sie ein FootballTeam, wenn Sie erwarten, eine einfache Liste? Kommentarautor: Flight Odyssey
was, wenn ich Ihnen sagen, dass ein football-team ist ein Unternehmen, in dessen Besitz sich eine Liste der Spieler Verträge statt einer bloßen Liste der Spieler mit einigen zusätzlichen Eigenschaften? Kommentarautor: STT LCU
Eigentlich ist es ganz einfach. IST ein Fußball-team eine Reihe von Spielern? Offensichtlich nicht, denn wie du sagst gibt es auch andere relevante Eigenschaften. Muss ein Fußball-team HABEN einen Kader von Spielern? Ja, so sollte es enthalten eine Liste. Other than, die Zusammensetzung ist nur vorzuziehen, um die Vererbung im Allgemeinen, denn es ist einfacher, Sie zu ändern später. Wenn Sie finden, Vererbung und Komposition, logische an der gleichen Zeit, gehen mit Zusammensetzung. Kommentarautor: Tobberoth
@FlightOdyssey: Angenommen, Sie haben eine Methode SquashRectangle, die in ein Rechteck, der Hälfte seiner Höhe, und verdoppelt seine Breite. Jetzt passen in ein Rechteck, das kommt vor ein 4x4, aber ist vom Typ Rechteck und ein Quadrat, das ist 4x4. Was sind die Abmessungen des Objekts nach SquashRectangle genannt wird? Für das Rechteck, klar, es ist 2x8. Wenn der Platz 2x8 dann ist es nicht mehr ein Quadrat; wenn es nicht 2x8 dann den gleichen Vorgang auf der gleichen Form erzeugt ein anderes Ergebnis. Die Schlussfolgerung ist, dass eine veränderliche Quadrat ist nicht, eine Art Rechteck. Kommentarautor: Eric Lippert
@Gangnus: Deine Aussage ist schlicht falsch; eine echte Unterklasse ist es erforderlich, dass Funktionen, die eine superset der Superklasse. Ein string muss, um alles ein object tun können, und mehr. Kommentarautor: Eric Lippert

InformationsquelleAutor der Frage Superbest | 2014-02-11

Schreibe einen Kommentar