4 Stimmen

Sollte ich eine Schnittstelle wie IEnumerable oder eine konkrete Klasse wie List<> verwenden?

Ich habe mich kürzlich an anderer Stelle* zu diesem Thema geäußert, aber ich denke, es verdient eine eingehendere Analyse, daher stelle ich diese Frage als eigenständige Frage.

Nehmen wir an, ich muss in meinem Programm einen Container erstellen und weitergeben. Ich habe wahrscheinlich keine starke Meinung über eine Art von Container gegenüber einer anderen, zumindest zu diesem Zeitpunkt, aber ich wähle einen aus; um der Argumentation willen, sagen wir, ich werde einen Liste<> .

Die Frage ist: Ist es besser, meine Methoden so zu schreiben, dass sie eine hochrangige Schnittstelle wie die von C# akzeptieren und zurückgeben? IEnumerable ? Oder sollte ich Methoden schreiben, um die spezifische Containerklasse, die ich gewählt habe, zu übernehmen und zu übergeben.

Auf welche Faktoren und Kriterien sollte ich bei meiner Entscheidung achten? Für welche Art von Programmen eignet sich das eine oder das andere? Beeinflusst die Computersprache Ihre Entscheidung? Leistung? Programmgröße? Persönlicher Stil?

(Ist das überhaupt wichtig?)

**(Hausaufgabe: Finden Sie sie. Aber bitte posten Sie Ihre Antwort hier, bevor Sie nach meiner suchen, um Sie nicht zu beeinflussen)*.

16voto

Rex M Punkte 138455

Ihre Methode sollte immer den am wenigsten spezifischen Typ akzeptieren, den sie zur Ausführung ihrer Funktion benötigt. Wenn Ihre Methode aufzählen muss, akzeptieren Sie IEnumerable . Wenn es zu tun hat IList<> -spezifischen Dingen, müssen Sie ihm per Definition eine IList<> .

5voto

Matt Hamilton Punkte 193704

Das Einzige, was Ihre Entscheidung beeinflussen sollte, ist, wie Sie den Parameter zu verwenden gedenken. Wenn Sie nur über ihn iterieren, verwenden Sie IEnumerable<T> . Wenn Sie auf indizierte Mitglieder zugreifen (z. B. var x = list[3] ) oder die Liste in irgendeiner Weise zu ändern (z. B. list.Add(x) ), dann verwenden Sie ICollection<T> o IList<T> .

3voto

TofuBeer Punkte 59410

Es gibt immer einen Kompromiss. Als Faustregel gilt, dass Dinge so weit oben in der Hierarchie wie möglich deklariert werden sollten. Wenn Sie also nur den Zugriff auf die Methoden in IEnumerable benötigen, sollten Sie diese verwenden.

Ein weiteres Beispiel für eine SO-Frage aus jüngster Zeit war eine C-API, die einen Dateinamen anstelle eines File * (oder Dateideskriptors) verwendete. Dort schränkte der Dateiname die Möglichkeiten der Übergabe stark ein (mit einem Dateideskriptor kann man viele Dinge übergeben, aber nur eines, das einen Dateinamen hat).

Sobald Sie mit dem Gießen beginnen müssen, sind Sie entweder zu weit gegangen ODER Sie sollten eine zweite Methode entwickeln, die einen spezifischeren Typ benötigt.

Die einzige Ausnahme, die ich mir vorstellen kann, ist, wenn Geschwindigkeit ein absolutes Muss ist und Sie den Aufwand eines virtuellen Methodenaufrufs nicht auf sich nehmen wollen. Durch die Deklaration des spezifischen Typs entfällt der Overhead virtueller Funktionen (das hängt von der Sprache/Umgebung/Implementierung ab, aber als allgemeine Aussage ist das wahrscheinlich richtig).

3voto

Daniel Earwicker Punkte 111630

Es war eine Diskussion mit mir, die diese Frage ausgelöst hat, also kennt Euro Micelli meine Antwort bereits, aber hier ist sie :)

Ich denke, Linq to Objects bietet bereits eine gute Antwort auf diese Frage. Durch die Verwendung der einfachsten Schnittstelle für eine Sequenz von Elementen bietet es maximale Flexibilität bei der Implementierung dieser Sequenz, was eine träge Generierung ermöglicht, die die Produktivität steigert, ohne die Leistung zu beeinträchtigen (nicht im eigentlichen Sinne).

Es stimmt, dass verfrühte Abstraktion einen Preis haben kann - aber hauptsächlich sind es die Kosten für die Entdeckung/Erfindung neuer Abstraktionen. Aber wenn man bereits perfekt funktionierende Abstraktionen zur Verfügung hat, dann wäre man verrückt, sie nicht zu nutzen, und das ist es, was die generischen Sammlungsschnittstellen bieten.

Manche werden Ihnen sagen, dass es "einfacher" ist, alle Daten in einer Klasse öffentlich zu machen, nur für den Fall, dass Sie darauf zugreifen müssen. Ebenso rät Euro, dass es besser wäre, eine reichhaltige Schnittstelle zu einem Container zu verwenden, wie z.B. IList<T> (oder sogar die konkrete Klasse List<T> ) und räumen dann später auf.

Aber ich denke, so wie es besser ist, die Datenelemente einer Klasse, auf die man nicht zugreifen will, zu verbergen, damit man die Implementierung dieser Klasse später leicht ändern kann, sollte man auch die einfachste verfügbare Schnittstelle verwenden, um auf eine Folge von Elementen zu verweisen. In der Praxis ist es einfacher, mit etwas Einfachem und Grundlegendem zu beginnen und es später "aufzulockern", als mit etwas Unbestimmtem zu beginnen und zu versuchen, es zu ordnen.

Also angenommen IEnumerable<T> ausreicht, um eine Sequenz darzustellen. In den Fällen, in denen Sie Folgendes benötigen Add o Remove Elemente benötigen (aber immer noch nicht nach dem Index suchen müssen), verwenden Sie IContainer<T> , das erbt IEnumerable<T> und ist daher perfekt mit Ihrem anderen Code kompatibel.

Auf diese Weise wird (allein durch die örtliche Untersuchung eines Codes) völlig klar, was dieser Code mit den Daten machen kann.

Es stimmt, dass kleine Programme weniger Abstraktion erfordern. Aber wenn sie erfolgreich sind, neigen sie dazu, zu großen Programmen zu werden. Das ist viel einfacher, wenn sie von vornherein einfache Abstraktionen verwenden.

0voto

Quintin Robinson Punkte 78652

Das ist wichtig, aber die richtige Lösung hängt ganz von der Verwendung ab. Wenn Sie nur eine einfache Aufzählung benötigen, dann verwenden Sie IEnumerable. Auf diese Weise können Sie jedem Implementierer den Zugriff auf die benötigten Funktionen ermöglichen. Wenn Sie jedoch Listenfunktionalität benötigen und Sie nicht eine neue Instanz einer Liste erstellen möchten, wenn zufällig jedes Mal, wenn die Methode aufgerufen wird, die Aufzählung, die übergeben wurde, keine Liste ist, dann verwenden Sie eine Liste.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X