Wygląda na to, że List<T>
w języku C # można zrobić wszystko, co tablica, i więcej, i wydaje się równie wydajna pod względem pamięci i wydajności, jak tablica.
Dlaczego więc miałbym kiedykolwiek chcieć używać tablicy?
Oczywiście nie pytam o przypadki, w których API lub inne zewnętrzne ograniczenie (tj. Funkcja Main) wymaga ode mnie użycia tablicy ... Pytam tylko o tworzenie nowych struktur danych we własnym kodzie.
c#
data-types
JoelFan
źródło
źródło
List<T>
is also just as efficient in memory and performance as an array
- um. Skąd masz takie pojęcie?var test = new string[5,5]
;)Odpowiedzi:
Z tego samego powodu, gdy nie jeżdżę ciężarówką, kiedy jadę do pracy. Nie używam czegoś, czego nie będę używać funkcji.
Przede wszystkim tablica jest prymitywną konstrukcją, więc tablica jest na pewno szybsza i wydajniejsza niż List <>, więc twój argument nie jest prawdziwy. Tablica jest również dostępna wszędzie i znana przez programistów używających różnych języków i platform.
Najważniejszym powodem, dla którego używam tablicy zamiast List <> jest sugerowanie, że dane mają stałą długość . Jeśli nie dodam ani nie usunę żadnych elementów z tego zbioru danych, chcę się upewnić, że typ to odzwierciedla.
Kolejną rzeczą jest założenie, że wdrażasz nową strukturę danych i przeczytałeś o niej kilka artykułów. Teraz, wdrażając określone algorytmy, nie zawsze możesz polegać na czyimś zastosowaniu typu ogólnego przeznaczenia. Zmienia się z .NET na Mono, a nawet pomiędzy różnymi wersjami frameworka.
Czasami łatwiej jest przenieść część kodu, który używa tablicy zamiast typu zależnego od frameworka.
źródło
List<T>
jest implementowana przy użyciu tablicy? Jeśli znasz wcześniej liczbę elementów (co musisz wiedzieć podczas korzystania z tablicy), możesz skorzystać z tej wiedzy podczas inicjowania listy.Potrzebujesz tablic, aby zarządzać kolekcją zmiennych struktur i oczywiście, co moglibyśmy zrobić bez nich.
(zwróć uwagę, że mogą istnieć przypadki, w których pożądana jest tablica modyfikowalnych struktur, ale zwykle to różne zachowanie modyfikowalnych struktur w obrębie tablic w porównaniu do innych kolekcji jest źródłem błędów, których należy unikać)
Mówiąc poważniej, potrzebujesz tablicy, jeśli chcesz przekazać element przez referencję . to znaczy
Może to być przydatne w przypadku kodu zabezpieczającego wątki bez blokady.
Potrzebujesz tablicy, jeśli chcesz szybko i skutecznie zainicjować kolekcję o stałym rozmiarze z wartością domyślną .
(zauważ, że byłoby możliwe zaimplementowanie konstruktora dla List, który robi to samo, po prostu c # nie oferuje tej funkcji)
potrzebujesz tablicy, jeśli chcesz efektywnie kopiować części kolekcji
(znowu, jest to coś, co można zaimplementować również dla List, ale ta funkcja nie istnieje w C #)
źródło
Rzadko będziesz miał scenariusz, w którym wiesz , że potrzebujesz stałej liczby elementów. Z punktu widzenia projektowania należy tego unikać. Jeśli potrzebujesz 3 rzeczy, natura biznesu oznacza, że bardzo często będziesz potrzebować 4 rzeczy w następnej wersji.
Mimo to, gdy tak naprawdę występuje ten rzadki scenariusz, przydatne jest użycie tablicy do wymuszenia niezmiennika o ustalonym rozmiarze. Daje to sygnał innym programistom, że ma ustalony rozmiar i pomaga zapobiegać niewłaściwemu użyciu, gdy ktoś dodaje lub usuwa element - przełamując oczekiwania w innym miejscu w kodzie.
źródło
Na twoje pytanie już wcześniej udzielono odpowiedzi .
To nie jest Z pytania, które podłączyłem:
Tablice są dwa razy szybsze w niektórych ważnych przypadkach. Jestem pewien, że użycie pamięci również różni się nietradycznie.
Ponieważ główna przesłanka twojego pytania została w ten sposób pokonana, zakładam, że to odpowiada na twoje pytanie. Ponadto czasami tablice są wymuszane na Tobie przez API Win32, moduł cieniujący twojego GPU lub inną bibliotekę inną niż DotNet.
Nawet w DotNet niektóre metody zużywają i / lub zwracają tablice (takie jak
String.Split
). Co oznacza, że albo trzeba teraz jeść koszt dzwoniToList
iToArray
przez cały czas, czy trzeba odpowiadać i użycie tablicy, ewentualnie kontynuując cykl propagując tym biednym dalszych użytkowników swoim kodzie.Więcej pytań i odpowiedzi na temat przepełnienia stosu na ten temat:
List<T>
: Kiedy użyć którego?List<>
?źródło
Oprócz powodów wymienionych w innych odpowiedziach literał tablicowy deklaruje mniej znaków:
Użycie tablicy zamiast
List
powoduje, że kod jest nieco krótszy i nieco bardziej czytelny w przypadkach, gdy (1) musisz podaćIEnumerable<T>
literał lub (2), gdzie inna funkcjonalnośćList
nie ma znaczenia i musisz użyć listy podobnej do listy dosłowny.Robiłem to od czasu do czasu w testach jednostkowych.
źródło
foreach( var x in new []{ a, b, c ) ) DoStuff( x )
lubnew []{ a, b, c ).Select( ... )
etcJest to ściśle z perspektywy OO.
Chociaż nie mogę wymyślić powodu, aby przekazać tylko tablicę, z pewnością widzę sytuacje, w których reprezentacja tablicy wewnątrz klasy jest prawdopodobnie najlepszym wyborem.
Chociaż istnieją inne opcje, które dają podobne cechy, żadna nie wydaje się tak intuicyjna jak tablica dla problemów związanych z przetwarzaniem permutacji, zagnieżdżona dla pętli, reprezentacji macierzy, map bitowych i algorytmów przeplatania danych.
Istnieje znaczna liczba dziedzin naukowych, które w dużym stopniu opierają się na matematyce matematycznej. (np. przetwarzanie obrazu, korekcja błędów danych, cyfrowe przetwarzanie sygnału, ryza zastosowanych problemów matematycznych). Większość algorytmów w tych polach jest napisana w kategoriach wykorzystania wielowymiarowych tablic / macierzy. Bardziej naturalne byłoby więc zaimplementowanie algorytmów, które są zdefiniowane, niż uczynienie ich bardziej „programowymi” przyjaznymi kosztem utraty bezpośrednich powiązań z dokumentami, na których oparte są algorytmy.
Tak jak powiedziałem, w tych przypadkach prawdopodobnie można uniknąć korzystania z list, ale to dodaje kolejną warstwę złożoności oprócz już złożonych algorytmów.
źródło
Dotyczy to również innych języków, które również mają listy (takich jak Java lub Visual Basic). Są przypadki, w których trzeba użyć tablicy, ponieważ metoda zwraca tablicę zamiast listy.
W prawdziwym programie nie sądzę, aby tablica była używana bardzo często, ale czasami wiesz, że dane będą miały stały rozmiar i podoba ci się niewielki wzrost wydajności uzyskiwany z używania tablicy. Mikrooptymalizacja byłaby słusznym powodem, podobnie jak metoda zwracająca listę lub potrzeba wielowymiarowej struktury danych.
źródło
list<T>
gdzievector<T>
będzie działać jest katastrofalnie złym pomysłem w C / C ++.vector<T> x
kompiluje dobrze dla mnie w C . :-)list<T>
. Zasadniczo widziałem wiele problemów z wydajnością spowodowanych przez programistów, którzy domyślnie używają list, gdy tablica była lepszym wyborem.Cóż, znalazłem zastosowanie tablic w grze, którą piszę. Użyłem go do stworzenia systemu ekwipunku ze stałą liczbą miejsc. Miało to kilka zalet:
Doszedłem do wniosku, że gdybym kiedykolwiek potrzebował „zwiększyć” rozmiar ekwipunku, mógłbym to zrobić, przenosząc stare przedmioty do nowej tablicy, ale ponieważ ekwipunek został ustalony na podstawie powierzchni ekranu i nie musiałem dynamicznie powiększać go / mniejsze, działało dobrze do celu, w którym go używałem.
źródło
Jeśli przemierzasz wszystkie elementy listy, to nie, tablica nie jest potrzebna, wystarczy „następna” lub dowolna „selekcja bez zamiany”.
Ale jeśli twój algorytm potrzebuje losowego dostępu do elementów w kolekcji, to tak, potrzebna jest tablica.
Jest to w pewnym sensie analogiczne do „czy jest to konieczne?”. W rozsądnym nowoczesnym języku wcale nie jest to potrzebne. Ale jeśli zdejmiesz abstrakcje, w pewnym momencie to wszystko, co naprawdę jest dla ciebie dostępne, to znaczy, jedynym sposobem na wdrożenie tych abstrakcji jest funkcja „niepotrzebnej”. (Oczywiście analogia nie jest idealna, nie sądzę, aby ktokolwiek twierdził, że tablice są słabą praktyką programowania; są łatwe do zrozumienia i przemyślenia).
źródło
List<T>
.Starsza kompatybilność.
Wszystkie tworzą osobiste doświadczenie:
Dawni programiści - mój kolega używa tablic wszędzie, robił to od ponad 30 lat, powodzenia zmieniając zdanie z twoimi nowymi wymyślonymi pomysłami.
Starszy kod - foo (pasek tablicy []) na pewno możesz użyć funkcji toarray listy / wektora / kolekcji, ale jeśli nie używasz żadnej z dodatkowych funkcji, łatwiej jest użyć tablicy na początku, często bardziej czytelnej bez zmiany typu.
Starszy szef - mój szef był dobrym programistą, zanim jeszcze wiele lat temu przeszła do zarządzania i nadal uważa, że jest na bieżąco, „używając tablic” może zakończyć spotkanie, wyjaśniając, jaką kolekcję może kosztować każdy lunch.
źródło
1) Nie ma wielowymiarowej wersji Listy. Jeśli dane mają więcej niż jeden wymiar, używanie list będzie bardzo nieefektywne.
2) Kiedy masz do czynienia z dużą liczbą małych typów danych (powiedzmy, mapa, w której wszystko, co masz, to jeden bajt dla typu terenu), mogą występować znaczne różnice wydajności z powodu buforowania. Wersja tablicy ładuje kilka elementów na odczytaną pamięć, wersja listy ładuje tylko jeden. Ponadto wersja tablicy zawiera kilka razy więcej komórek w pamięci podręcznej niż wersja listy - jeśli wielokrotnie przetwarzasz dane, może to mieć dużą różnicę, jeśli wersja tablicy mieści się w pamięci podręcznej, ale wersja listy nie.
W skrajnym przypadku rozważ grę Minecraft. (Tak, nie jest napisane w języku C #. Dotyczy to tego samego powodu.)
źródło
T[,]
) Są wolniejsze niż równoważne tablice poszarpane (npT[][]
. ) .100-elementowa tablica pewnego typu T zawiera 100 niezależnych zmiennych typu T. Jeśli T jest typem wartości, który ma zmienne pole publiczne typu Q i jedno typu R, to każdy element tablicy będzie zawierał zmienne niezależne typu Q i R. Tablica jako całość będzie zatem zawierała 100 zmiennych niezależnych typu Q i 100 zmiennych niezależnych typu R; do każdej z tych zmiennych można uzyskać dostęp indywidualnie, bez wpływu na inne. Żaden typ kolekcji inny niż tablice nie pozwala na stosowanie pól struktur jako zmiennych niezależnych.
Jeśli zamiast tego T okazał się typem klasy z publicznie zmiennymi polami typu Q i R, każdy element tablicy zawiera jedyne odniesienie, w dowolnym miejscu we wszechświecie, do instancji użycia tablicy lub zbioru typu zmiennej klasy, co stwarza możliwość że zmienne identyfikowane przez elementy tablicy mogą nie być niezależne .
T
i, jeśli żaden z elementów tablicy nigdy nie będzie zostać zmodyfikowane w celu zidentyfikowania obiektu, do którego istnieje jakiekolwiek odniesienie zewnętrzne, wówczas tablica skutecznie obuduje 100 zmiennych niezależnych typu Q i 100 zmiennych niezależnych typu R. Inne typy kolekcji mogą naśladować zachowanie takiej tablicy, ale jeśli jest to jedyny cel tablicy służy do enkapsulacji 100 zmiennych typu Q i 100 typu R, enkapsulacja każdej pary zmiennych w obiekcie własnej klasy jest drogim sposobem na zrobienie tego. Dalej,Jeśli typ ma zachowywać się jak jakiś obiekt, to powinien być albo typem klasy, albo strukturą pola prywatnego, która nie zapewnia żadnej innej mutacji niż zamiana. Jeśli jednak typ ma zachowywać się jak wiązka pokrewnych, ale niezależnych zmiennych sklejonych razem z taśmą klejącą, wówczas należy użyć typu, który jest wiązką zmiennych sklejonych razem z taśmą klejącą - struktura pola odsłoniętego . Tablice tego typu są bardzo wydajne w pracy i mają bardzo czystą semantykę. Użycie dowolnego innego typu doprowadzi do mętnej semantyki, gorszej wydajności lub obu.
źródło
Ważną różnicą jest przydział pamięci. Na przykład przeglądanie połączonej listy może spowodować wiele braków pamięci podręcznej i spowolnienie wydajności, podczas gdy tablica reprezentuje ciągłą część pamięci zawierającą wiele instancji określonego typu danych, a wykonywanie tej operacji w kolejności jest bardziej prawdopodobne, że uderzy w procesor Pamięć podręczna.
Oczywiście tablica odwołań do obiektów może nie odnieść tak dużych korzyści z trafień w pamięci podręcznej, ponieważ dereferencje mogą nadal zabrać Cię w dowolne miejsce w pamięci.
Następnie są implementacje list, takie jak ArrayList, które implementują listę za pomocą tablicy. Są to przydatne prymitywy.
źródło
List<T>
, który nie jest zaimplementowany za pomocą listy połączonej, ale za pomocą tablicy (w zasadzie jest to odpowiednikArrayList<T>
w Javie).Oto kilka wskazówek, z których możesz skorzystać, kiedy
Array
i kiedy wybraćList
.Array
gdy wracasz z metody.List
jako zmiennej podczas konstruowania wartości zwracanej (wewnątrz metody). Następnie użyj,.ToArray()
gdy wracasz z metody.Ogólnie rzecz biorąc, użyj,
Array
gdy nie zamierzasz dodawać produktów do kolekcji. Użyj,List
gdy zamierzasz dodać produkty do kolekcji.Array
jest przeznaczony do obsługi kolekcji „statycznych”, podczas gdyList
jest przeznaczony do obsługi kolekcji „dynamicznych”.źródło
Array
zamiastList
. Miło słyszeć twoje myśli!