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 IList
do a, List
aby móc dodawać wartości bez ryzyka błędów. Oczywiście mogą sprawdzić typoszereg, aby sprawdzić, czy mają do czynienia z a List
lub an Array
, ale jeśli tego nie robią i chcą dodać elementy do kolekcji, nie mają innego wyboru, aby skopiować IList
do 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życieCount
właściwości zamiast wyliczania).