Schnittstelle oder Klasse zurückgeben

9

Angenommen, ich habe eine Methode

public List<User> GetBatchOfUsers(IEnumerable<int> userIDs)
{
    List<User> users = new List<User>();

    // some database stuff

    return users;
}

Ich habe gelesen, dass es besser wäre, eine Schnittstelle (entweder IListoder IEnumerable) zurückzugeben, als eine zurückzugeben List. Einige Argumente, die ich dafür gehört habe, sind, dass es Daten verbirgt und dem API-Entwickler die Flexibilität gibt, die interne Darstellung der Daten zu einem späteren Zeitpunkt zu ändern.

Ich mache mir Sorgen, IEnumerabledass Sie nur Funktionen zurückgeben, z. B. den wahlfreien Zugriff und die CountEigenschaft.

Ich weiß, dass das Akzeptieren eines IEnumerableals Parameter sinnvoll ist, da es dem Verbraucher die beste Flexibilität bietet, Daten an meine Methode zu senden, die minimalistischen Anforderungen für die Funktionsweise der Methode.

Was ist die beste Vorgehensweise für den Rückgabetyp?

Matthew
quelle
5
Viel wichtiger: Nehmen Sie eine Schnittstelle als Parametertyp.
Michael Borgwardt

Antworten:

10

Im Allgemeinen können Sie mit Schnittstellen beginnen und den konkreten Typ nur dann als Rückgabetyp festlegen, wenn Sie feststellen, dass Sie die zusätzlichen Methoden häufiger als erwartet verwenden.

Wenn Sie eine Schnittstelle zurückgeben, behalten Sie mehr Flexibilität. Sie können die Implementierung später ändern, um einen anderen konkreten Typ zurückzugeben. Andererseits gibt es dem Anrufer offensichtlich weniger Informationen, so dass er möglicherweise bestimmte Vorgänge nicht ausführen kann. (Beispiel: Wenn Sie zurückkehren List<T>, kann der Aufrufer ConvertAll usw. verwenden, was er nicht kann, wenn Sie nur erklären, dass Sie zurückkehren IList<T>.) In einigen Situationen lohnt es sich, den konkreten Typ anzugeben.

In Bezug auf die Count- oder Sortiermethode gibt es dafür keine Standard-Erfassungsschnittstellen. Sie können jedoch eine Erweiterungsmethode schreiben, um IList zu sortieren oder zu zählen.

Yusubov
quelle
Ich denke, das ist dann keine wirklich harte Regel?
Matthew
Ja, es hängt wirklich von der Nutzung ab.
Yusubov
1

Wenn Sie eine Sammlung benötigen, können CountSie diese verwenden ICollection<T>, was allgemein genug ist.

dpiatkowski
quelle
-1. Count wurde bereits besprochen und diese Antwort fügt nichts Neues hinzu
superM
@Konrad Rudolph, das ist keine Antwort, es ist ein Kommentar.
SuperM
@superM Es ist wertvoll genug, um eine eigene Antwort zu verdienen, denke ich, da es explizit den Grund von OP anspricht, sich überhaupt gegen Schnittstellen zu entscheiden.
Konrad Rudolph
1

Sie geben zurück, was für die von Ihnen definierte Methode sinnvoll ist. Gibt das, was Sie tun, eine Reihe von Elementen zurück (der Fokus liegt auf den Elementen), oder gibt es eine Sammlung von Elementen zurück (der Fokus liegt auf der Sammlung als Ganzes)? Lohnt es sich, Abweichungen bei der Implementierung der Sammlung zuzulassen? Wenn es nie Sinn macht, einen Generator zu verwenden, oder verwenden Sie HashSeteinfach den List.

Telastyn
quelle
1

Spezifisch für die Beispielmethode: Sie haben Recht, dass eine Rückgabe IEnmuerable<T>bedeuten würde, dass Sie die Funktionalität Countund Indizierung verlieren würden (obwohl Sie LINQ-Methoden verwenden könnten Count()und ElementAt()diese effizient implementiert werden, wenn der Typ, für den sie verwendet werden, tatsächlich implementiert wird IList<T>).

Wenn Sie zurückkehren IList<T>, verlieren Sie einige Funktionen, aber der Gewinn an Allgemeinheit ist es wahrscheinlich wert.

Aber noch besser wäre etwas zwischen IEnumerable<T>und IList<T>, da es für den Verbraucher höchstwahrscheinlich keinen Sinn macht, die zurückgegebene Sammlung zu mutieren, aber es für ihn sinnvoll ist, sie zu verwenden Countoder zu indizieren.

In .Net 4.5 gibt es eine solche Schnittstelle : IReadOnlyList<T>.

svick
quelle
IReadOnlyListklingt gut, wenn ich VS2013 bekommen kann, danke!
Matthew