Aby odpowiedzieć na pytanie „dlaczego”, dlaczego nie List<T>
, powody są przyszłościowe i prostota API.
Gotowość na przyszłość
List<T>
nie jest zaprojektowany tak, aby można go było łatwo rozszerzać poprzez tworzenie podklas; został zaprojektowany tak, aby był szybki we wdrożeniach wewnętrznych. Zauważysz, że metody na nim nie są wirtualne i dlatego nie można ich zastąpić, i nie ma żadnych punktów zaczepienia w jego operacjach Add
/ Insert
/ Remove
.
Oznacza to, że jeśli będziesz musiał zmienić zachowanie kolekcji w przyszłości (np. Aby odrzucić obiekty puste, które ludzie próbują dodać, lub wykonać dodatkową pracę, gdy tak się stanie, np. Zaktualizować stan twojej klasy), musisz zmienić typ kolekcji, wrócisz do takiej, którą możesz podklasować, co będzie zepsutą zmianą interfejsu (oczywiście zmiana semantyki rzeczy, takich jak niedopuszczanie do wartości null, może być również zmianą interfejsu, ale rzeczy takie jak aktualizacja wewnętrznego stanu klasy nie byłyby).
Dlatego zwracając klasę, którą można łatwo podzielić na podklasę, taką jak Collection<T>
lub interfejs, taki jak IList<T>
, ICollection<T>
lub IEnumerable<T>
możesz zmienić wewnętrzną implementację, aby była innym typem kolekcji, aby spełnić Twoje potrzeby, bez łamania kodu konsumentów, ponieważ nadal można ją zwrócić jako rodzaj, jakiego oczekują.
Prostota interfejsu API
List<T>
zawiera wiele przydatnych funkcji, takich jak BinarySearch
, Sort
i tak dalej. Jednak jeśli jest to kolekcja, którą ujawniasz, prawdopodobnie kontrolujesz semantykę listy, a nie konsumentów. Więc chociaż twoja klasa wewnętrznie może potrzebować tych operacji, jest bardzo mało prawdopodobne, że konsumenci twojej klasy będą chcieli (lub nawet powinni) je wywoływać.
W związku z tym, oferując prostszą klasę kolekcji lub interfejs, zmniejszasz liczbę członków, których widzą użytkownicy Twojego interfejsu API, i ułatwiasz im korzystanie.