2009-02-21 16 views
7

Mam klasę Customer (z typowymi właściwościami klienta) i muszę przekazać, a databind, "porcję" instancji Customer. Obecnie używam tablicy Customer, ale użyłem także Collection z T (i List z zanim dowiedziałem się o Collection z T). Chciałbym najcieńszy sposób, aby przekazać ten fragment przy użyciu C# i .NET 3.5.ArrayList versus array of objects versus Collection of T

Obecnie układ Customer działa dobrze dla mnie. Dane te dobrze się wiążą i wydaje się, że są tak lekkie, jak to tylko możliwe. Nie potrzebuję produktów List z T z ofertami i Collection z T nadal wydaje się przesadą. Tablica wymaga ode mnie wcześniejszej informacji, ile dodać do porcji, ale zawsze wiem o tym wcześniej (na przykład podane wiersze na stronie).

Czy brakuje mi czegoś podstawowego lub jest to zestaw Customer OK? Czy brakuje mi kompromisu?

Ponadto zakładam, że Collection z T powoduje, że stary, luźno wpisany ArrayList staje się przestarzały. Czy jestem tam?

Odpowiedz

4

Nikt nie wspomniał rady wytyczne ramowe: Don't use List<T> in public API's:

Nie zalecamy korzystania List w API publicznych z dwóch powodów.

  • List<T> nie jest przeznaczony do przedłużenia. Oznacza to, że nie można przesłonić żadnych członków . Oznacza to na przykład, że obiekt zwracający List<T> z właściwości nie będzie mógł uzyskać powiadomienia , gdy kolekcja zostanie zmodyfikowana. Collection<T> pozwala zastąpić chroniony element SetItem, aby uzyskać "powiadomiony" o dodaniu nowego elementu lub zmiana istniejącego elementu.

  • Lista ma wielu członków, którzy nie są związani z wieloma scenariuszami. Mamy powiedzieć, że List<T> jest zbyt "zajęty" dla publicznych modeli obiektów . Wyobraź sobie: ListView.Items właściwość powracająca List<T> z całym jej bogactwem. Teraz, , spójrz na rzeczywisty typ zwrotu: ListView.Items ; to sposób prostszy i podobny do Collection<T> lub ReadOnlyCollection<T>

Ponadto, jeśli twoim celem jest dwukierunkowa Databinding, rzucić okiem na BindingList<T> (z zastrzeżeniem, że nie jest sortable „out of the box '!)

11

Tak, Collection<T> (lub List<T> częściej) sprawia, że ​​ArrayList jest dość przestarzałe. W szczególności, uważam, że ArrayList nie jest nawet obsługiwany w Silverlight 2.

Tablice są w porządku w niektórych przypadkach, ale powinny być considered somewhat harmful - mają różne wady. (Są one w głównej mierze częścią większości zbiorów, oczywiście ...). Wchodzę w szczegóły, ale Eric Lippert robi to o wiele lepiej niż kiedykolwiek w artykule, do którego odnosi się link. Chciałbym to podsumować tutaj, ale to dość trudne. Naprawdę warto po prostu przeczytać cały post.

+0

Ma świetną robotę w tym artykule, dobrą lekturę dla każdego, kto jeszcze tego nie zrobił. –

3

Generalnie, należy „przejść wokół” IEnumerable <T> lub kolekcji ICollection <T> (w zależności od tego, czy ma to sens dla konsumenta, aby dodać swoją pozycje).

0

Mam zamiar przedstawić argumenty przeciwne zarówno Jonowi, jak i Ericowi Lippertowi), co oznacza, że ​​powinniście być bardzo zmęczeni moją odpowiedzią!).

Sercem argumentów Eric Lipperta wobec tablic jest to, że zawartość jest niezmienna, podczas gdy sama struktura danych nie jest. Jeśli chodzi o zwracanie ich z metod, zawartość listy jest tak samo zmienna. W rzeczywistości, ponieważ można dodawać lub odejmować elementy z listy, twierdzę, że powoduje to, że wartość zwracana jest bardziej zmienna niż tablica.

Innym powodem, dla którego lubię tablice, jest fakt, że kiedyś wróciłem do małej sekcji kodu krytycznego pod względem wydajności, więc porównałem charakterystykę wydajności tych dwóch, a tablice wysadziły listy z wody. Teraz, pozwólcie, że to zastrzeżę, mówiąc, że był to wąski test na to, jak zamierzam ich użyć w konkretnej sytuacji, i jest to sprzeczne z tym, co rozumiem w obu przypadkach, ale liczby były szalenie różne.

W każdym razie, posłuchaj Jon i Eric =), i zgadzam się, że lista prawie zawsze ma więcej sensu.

+0

Są z pewnością miejsca, w których używanie tablic ma sens, a oni rzeczywiście będą działali lepiej. To jest powód, aby ich używać * tam, gdzie wydajność jest krytyczna * (co nie jest zbyt wiele miejsc IME).Dla argumentu immutability: jeśli zadeklarujesz, że metoda zwraca Foo [], to * zawsze * będzie zmienne. –

+0

Jeśli, z drugiej strony, deklarujesz, że zwraca IList , wówczas zwracana wartość * może * być zmienna lub * może * być niezmienna - i możesz bardzo łatwo zbudować opakowanie tylko do odczytu. To nie tyle przypadek "array vs List " jak "array vs interface" dla typów zwracanych. –

+0

Nie możesz jednak zwrócić tablicy Array of IImmutableObject []? Nie próbuję być kłótliwy, ale ten argument nigdy nie miał dla mnie sensu. (Jeśli ktoś uważa, że ​​moja argumentacja jest przekonująca, należy użyć listy , ponieważ jest to właściwe działanie w 99,9% przypadków). – Travis

0

Zgadzam się z Alun, z jednym dodatkiem. Jeśli chcesz zwrócić wartość zwracaną przez indeks myArray [n], użyj IList.

Tablica z natury wspiera IList (a także IEnumerable i ICollection, jeśli o to chodzi). Jeśli więc przechodzisz przez interfejs, nadal możesz używać tablicy jako podstawowej struktury danych. W ten sposób, sposoby, które przechodzą do tablicy nie musi „wiedzieć”, że podstawowe datastructure jest tablicą:

 public void Test() 
{ 
    IList<Item> test = MyMethod(); 
} 

public IList<Item> MyMethod() 
{ 
    Item[] items = new Item[] {new Item()}; 
    return items; 
} 
1

Jeśli masz niezmienne listę klientów, która jest ... twoja lista klientów się nie zmieni, jest względnie mała i zawsze będziesz ją powtarzać od początku do końca i nie musisz dodawać do listy ani usuwać z niej, więc tablica jest prawdopodobnie w porządku.

Jeśli nie masz pewności, najlepszym z nich jest pewna kolekcja. Wybór kolekcji zależy od operacji, które chcesz wykonać. Kolekcje dotyczą wstawiania, manipulacji, wyszukiwań i usuwania. Jeśli często korzystasz z wyszukiwania danego elementu, najlepszym rozwiązaniem może być słownik. Jeśli chcesz posortować dane, być może SortedList będzie działał lepiej.

Nie przejmowałbym się "lekkością", chyba że mówimy o ogromnej liczbie elementów, a nawet wtedy zalety O (1) sprawdzeń przewyższają koszty zasobów.

Gdy "przechodzisz dookoła" kolekcji, tylko przekazujesz referencję, która jest w zasadzie wskaźnikiem. Nie ma więc różnicy w wydajności między przekazywaniem kolekcji a tablicą.