Załóżmy, że mam metodę
public List<User> GetBatchOfUsers(IEnumerable<int> userIDs)
{
List<User> users = new List<User>();
// some database stuff
return users;
}
Przeczytałem, że lepiej byłoby zwrócić interfejs (albo IList
albo IEnumerable
), niż zwrócić a List
. Niektóre argumenty, które słyszałem, to to, że ukrywa dane i daje programistom API elastyczność zmiany wewnętrznej reprezentacji danych w późniejszym terminie.
Moją obawą przed zwrotem IEnumerable
jest utrata funkcjonalności, takiej jak losowy dostęp i Count
właściwość.
Wiem, że przyjęcie IEnumerable
parametru jako parametru ma sens, ponieważ daje konsumentowi najlepszą elastyczność w wysyłaniu danych do mojej metody, minimalistycznego zestawu wymagań dla metody do działania.
Jaka jest najlepsza praktyka dla typu zwrotu?
c#
interfaces
class
Mateusz
źródło
źródło
Odpowiedzi:
Ogólnie rzecz biorąc, możesz zacząć od interfejsów i przejść do umieszczenia konkretnego typu jako typu zwracanego, jeśli zauważysz, że korzystasz z dodatkowych metod częściej niż oczekiwano.
Cóż, jeśli zwrócisz interfejs, zachowasz większą elastyczność. Możesz zmienić implementację później, aby zwrócić inny konkretny typ. Z drugiej strony, w oczywisty sposób przekazuje dzwoniącemu mniej informacji, więc może nie być w stanie wykonać pewnych operacji. (Na przykład: jeśli wrócisz
List<T>
, dzwoniący może użyć ConvertAll itp. ... czego nie może, jeśli tylko zadeklarujesz, że wróciszIList<T>
.) W niektórych sytuacjach warto określić konkretny typ.Jeśli chodzi o metodę Count lub Sort, nie ma do tego standardowych interfejsów kolekcji. Możesz jednak napisać metodę rozszerzenia, aby posortować lub policzyć dowolną IList.
źródło
Jeśli potrzebujesz swojej kolekcji,
Count
abyś mógł z niej korzystaćICollection<T>
, co jest dość ogólne.źródło
Zwraca to, co jest ostrożne dla metody, którą definiujesz. Czy to, co robisz, zwracając serię przedmiotów (koncentrujesz się na przedmiotach), czy też zwracasz kolekcję przedmiotów (koncentrujesz się na kolekcji jako całości)? Czy warto pozwolić na wariancję w realizacji kolekcji? Jeśli to nie będzie sensu używać generatora lub
HashSet
potem po prostu używaćList
.źródło
Specyficzne dla przykładowej metody: Masz rację, że zwracanie
IEnmuerable<T>
oznaczałoby utratę funkcjonalnościCount
i indeksowania (chociaż możesz użyć metod LINQCount()
iElementAt()
, które są skutecznie zaimplementowane, jeśli typ, na którym są używaneIList<T>
).Jeśli wrócisz
IList<T>
, stracisz trochę funkcjonalności, ale prawdopodobnie zyskujesz na ogólności.Ale jeszcze lepiej byłoby coś pomiędzy
IEnumerable<T>
iIList<T>
, ponieważ najprawdopodobniej nie ma sensu mutować zwracanej kolekcji przez konsumenta, ale ma sens użycieCount
lub indeksowanie.W .NET 4.5, istnieje taki interfejs:
IReadOnlyList<T>
.źródło
IReadOnlyList
brzmi dobrze, kiedy mogę zdobyć VS2013, dzięki!