Odpowiedzi na takie pytania: List <T> lub IList <T> zawsze wydają się zgadzać, że zwrócenie interfejsu jest lepsze niż zwrócenie konkretnej implementacji kolekcji. Ale walczę z tym. Utworzenie wystąpienia interfejsu jest niemożliwe, więc jeśli metoda zwraca interfejs, w rzeczywistości nadal zwraca określoną implementację. Trochę z tym eksperymentowałem, pisząc dwie małe metody:
public static IList<int> ExposeArrayIList()
{
return new[] { 1, 2, 3 };
}
public static IList<int> ExposeListIList()
{
return new List<int> { 1, 2, 3 };
}
I użyj ich w moim programie testowym:
static void Main(string[] args)
{
IList<int> arrayIList = ExposeArrayIList();
IList<int> listIList = ExposeListIList();
//Will give a runtime error
arrayIList.Add(10);
//Runs perfectly
listIList.Add(10);
}
W obu przypadkach, gdy próbuję dodać nową wartość, mój kompilator nie daje mi żadnych błędów, ale oczywiście metoda, która ujawnia moją tablicę jako a, IList<T>daje błąd w czasie wykonywania, gdy próbuję coś do niej dodać. Dlatego ludzie, którzy nie wiedzą, co dzieje się w mojej metodzie i muszą dodać do niej wartości, są zmuszeni najpierw skopiować moje IListdo a, Listaby móc dodawać wartości bez ryzyka błędów. Oczywiście mogą sprawdzić typoszereg, aby sprawdzić, czy mają do czynienia z a Listlub an Array, ale jeśli tego nie robią i chcą dodać elementy do kolekcji, nie mają innego wyboru, aby skopiować IListdo a List, nawet jeśli to już jestList . Czy tablica nigdy nie powinna być ujawniona jako IList?
Inna moja obawa opiera się na zaakceptowanej odpowiedzi na powiązane pytanie (moje wyróżnienie):
Jeśli udostępniasz swoją klasę za pośrednictwem biblioteki, z której będą korzystać inni, generalnie chcesz udostępnić ją za pośrednictwem interfejsów, a nie konkretnych implementacji. Pomoże to, jeśli później zdecydujesz się zmienić implementację swojej klasy, aby użyć innej konkretnej klasy. W takim przypadku użytkownicy Twojej biblioteki nie będą musieli aktualizować swojego kodu, ponieważ interfejs się nie zmienia.
Jeśli używasz go tylko wewnętrznie, możesz nie przejmować się tak bardzo, a korzystanie z listy może być w porządku.
Wyobraź sobie, że ktoś faktycznie użył mojej metody, IList<T>którą otrzymałem z mojej ExposeListIlist()metody, właśnie w ten sposób, aby dodać / usunąć wartości. Wszystko dziala. Ale teraz, jak sugeruje odpowiedź, ponieważ zwracanie interfejsu jest bardziej elastyczne, zwracam tablicę zamiast listy (nie ma problemu z mojej strony!), A potem czeka ich przyjemność ...
TLDR:
1) Odsłonięcie interfejsu powoduje niepotrzebne rzuty? Czy to nie ma znaczenia?
2) Czasami, jeśli użytkownicy biblioteki nie używają rzutowania, ich kod może się zepsuć, gdy zmienisz metodę, nawet jeśli metoda pozostaje w porządku.
Prawdopodobnie zbytnio się nad tym zastanawiam, ale nie mam ogólnego konsensusu, że zwracanie interfejsu jest lepsze niż zwracanie implementacji.
IEnumerable<T>i masz czas na kompilację. Nadal można używać wszystkich metod rozszerzenia LINQ, które zwykle próbują zoptymalizować wydajność, rzutując ją na określony typ (podobnieICollection<T>jak użycieCountwłaściwości zamiast wyliczania).