Frage

Was ist der bevorzugte Behältertyp, wenn von einer Funktion mehrere Objekte des gleichen Typs zurückkehrt?

Ist es gegen gute Praxis ein einfaches Array (wie MyType []) zurückzukehren, oder sollten Sie es in einigen generischen Container wickeln (wie ICollection )?

Danke!

War es hilfreich?

Lösung

Eric Lippert hat einen guten Artikel zu diesem Thema. Für den Fall, können Sie den gesamten Artikel zu lesen gestört werden, lautet die Antwort:. Die Schnittstelle zurückkehren

Andere Tipps

Gibt einen IEnumerable<T> mit einem yield return .

Ich würde ein IList<T> zurückkehren, dass die Verbraucher von Ihrer Funktion der größte Flexibilität. Auf diese Weise, wenn der Verbraucher Ihrer Funktion benötigt nur die Reihenfolge aufzuzählen sie dies tun können, aber wenn sie die Sequenz als eine Liste verwenden möchten, können sie das auch tun.

Meine Faustregel ist es, die am wenigsten restriktive Typ als Parameter und gibt die reichste Typ akzeptieren ich kann. Dies ist natürlich, ein Balanceakt, wie Sie wollen nicht selbst in eine bestimmte Schnittstelle oder Implementierung sperren (aber immer, immer versuchen, eine Schnittstelle zu verwenden).

Dies ist die am wenigsten anmaßend Ansatz, die Sie, den API-Entwickler, nehmen. Es ist nicht an Ihnen zu entscheiden, wie ein Verbraucher Ihrer Funktion nutzen, was sie Ihnen schicken - das ist, warum Sie eine IList<T> würde in diesem Fall zurück, wie sie die größtmögliche Flexibilität zu geben. Auch aus diesem gleichen Grunde würden Sie nie zu wissen, vermuten, welche Art von Parametern ein Verbraucher schickt. Wenn Sie nur eine Sequenz als Parameter gesendet iterieren müssen dann die Parameter macht eine IEnumerable<T> eher als ein List<T>.


EDIT (Monoxid): Da es nicht sieht, wie die Frage geschlossen werden soll, ich will nur einen Link von der anderen Frage zu diesem hinzuzufügen: Warum Arrays sind schädlich

Warum nicht List<T>?

Von der Eric Lippert Post von anderen erwähnt, ich dachte ich, das werde Highlights:

  

Wenn ich eine Folge benötigen werde ich verwenden   IEnumerable<T>, wenn ich brauche eine Zuordnung   von angrenzenden Zahlen Daten werde ich   verwenden, um ein List<T>, wenn ich eine Abbildung benötigen   über beliebige Daten werde ich ein verwenden   Dictionary<K,V>, wenn ich einen Satz benötigen werde ich   verwenden, um eine HashSet<T>. Ich einfach nicht brauchen   fast Arrays für etwas, so dass ich nie   benutze sie. Sie lösen nicht ein Problem, das ich   haben besser als die anderen Werkzeuge an meinem   Entsorgung.

Wenn die Sammlung, die zurückgegeben wird, ist schreibgeschützt, das heißt, Sie nie die Elemente in der Sammlung sollen geändert werden, dann IEnumerable<T> verwenden. Dies ist die einfachste Darstellung einer Nur-Lese-Folge von unveränderlichen (zumindest aus Sicht der Enumeration selbst) Elemente.

Wenn Sie es wollen, eine in sich geschlossene Sammlung sein, die geändert werden können, dann verwenden ICollection<T> oder IList<T>.

Zum Beispiel, wenn Sie die Ergebnisse der Suche nach einem bestimmten Satz von Dateien, dann wieder IEnumerable<FileInfo> zurückkehren wollen.

Wenn Sie jedoch die Dateien in einem Verzeichnis, jedoch aussetzen wollen, würden setzen Sie IList/ICollection<FileInfo> wie es Sinn macht, dass man sich nur wünschen würde, um den Inhalt der Sammlung zu ändern.

Ein guter Ratschlag, den ich oft zitierte gehört habe, ist dies:

  

Seien Sie liberal, was Sie akzeptieren, genau in dem, was Sie zur Verfügung stellen.

In Bezug auf Ihre API entwerfen, würde ich vorschlagen, sollten Sie eine Schnittstelle zurückkehren, kein konkreter.

Unter Ihrer Beispiel Methode, ich würde es wie folgt umschreiben:

public IList<object> Foo() 
{
    List<object> retList = new List<object>();
    // Blah, blah, [snip]
    return retList;
}

Der Schlüssel ist, dass Ihre interne Implementierung Wahl - eine Liste zu verwenden - nicht mit dem Anrufer aufgedeckt, aber Sie eine entsprechende Schnittstelle bist zurück.

Microsofts eigene Richtlinien zur Rahmen Entwicklung empfehlen gegen bestimmte Arten der Rückkehr begünstigen Schnittstellen. (Sorry, ich kann nicht einen Link für diese finden)

In ähnlicher Weise Ihre Parameter sollten so allgemein wie möglich sein - stattdessen eine Reihe von zu akzeptieren, eine IEnumerable des entsprechenden Typs akzeptieren. Dies ist kompatibel mit Arrays sowie Listen und anderen nützlichen Typen.

Unter Ihren Beispielverfahren wieder:

public IList<object> Foo(IEnumerable<object> bar) 
{
    List<object> retList = new List<object>();
    // Blah, blah, [snip]
    return retList;
}
return ICollection<type>

Der Vorteil generische Rückgabetypen, ist, dass Sie die zugrunde liegende Implementierung ändern können, ohne den Code zu ändern, die es verwendet. Der Vorteil für die spezifische Art Rückkehr, ist, dass Sie mehr typspezifische Methoden verwenden können.

Immer einen Schnittstellentyp zurückgeben, die die größte Menge an Funktionalität mit dem Anrufer präsentiert. Also in Ihrem Fall ICollection<YourType> sollte verwendet werden.

Etwas interessant zu bemerken ist, dass die BCL-Entwickler diese falsch verstanden tatsächlich in einem Ort des .NET-Frameworks - siehe diese Eric Lippert Blog-Post für diese Geschichte.

Warum nicht IList<MyType>?

Es unterstützt die direkte Indizierung, die für ein Array Markenzeichen ist ohne die Möglichkeit, das Entfernen eines List<MyType> eines Tages zurückzukehren. Wenn Sie diese Funktion zu unterdrücken wollen, möchten Sie wahrscheinlich IEnumerable<MyType> zurückzukehren.

Es hängt davon ab, was Sie vorhaben, mit der Sammlung zu tun, du bist zurück. Wenn Sie nur das Iterieren sind, oder wenn Sie nur der Benutzer wiederholen wollen, dann bin ich mit @ Daniel, Rückkehr IEnumerable<T>. Wenn Sie tatsächlich listenbasierte Operationen zulassen wollen, jedoch würde ich zurückkehren IList<T>.

Mit Generika. Es ist einfacher zu interoperabel mit anderen Sammlungen Klassen und das Typsystem ist mehr in der Lage Ihnen mögliche Fehler zu helfen.

Der alte Stil der Rückgabe eines Arrays eine Krücke vor Generika wurde.

Was auch immer macht den Code besser lesbar, wartbar und einfacher für Sie. Ich hätte die einfache Array, einfacher == besser die meiste Zeit verwendet. Obwohl ich wirklich den Kontext zu sehen, die richtige Antwort zu geben.

Es gibt große Vorteile zu begünstigen IEnumerable über irgendetwas anderes, da dies gibt Ihnen die größte Implementierung Flexibilität und ermöglicht es Ihnen yield return oder Linq Betreiber für faule Implementierung zu verwenden.

Wenn der Anrufer will ein List<T> stattdessen können sie einfach ToList() rufen auf, was Sie zurückgeschickt, und die Gesamtleistung wird in etwa das gleiche wie wenn man geschaffen hatte und kehrte ein neues List<T> aus Ihrer Methode.

Array ist schädlich, aber ICollection<T> ist auch schädlich.

ICollection<T> kann das Objekt nicht garantieren, wird unveränderlich.

Meine Empfehlung ist, das zurückkehrende Objekt mit ReadOnlyCollection<T> zu wickeln

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top