Tablica przechowuje stałą liczbę elementów jednego typu, ułożonych w pamięci jeden obok drugiego. Długość wybierasz przy tworzeniu, elementy odczytujesz i zapisujesz przez indeks liczony od zera, a długość potem już się nie zmienia.
Deklarowanie i inicjalizacja tablicy
Typ tablicy to typ elementu, po którym stoi []. Tablicę można utworzyć na kilka sposobów:
Wynik:
90, 0, 0, 72
Ben
2 prices, 3 days
new int[4] wypełnia każdy element wartością domyślną typu: 0 dla liczb, false dla bool, null dla napisów i innych typów referencyjnych. Krótka forma { "Ana", "Ben" } działa tylko w deklaracji; przy przypisaniu do istniejącej zmiennej potrzebujesz names = new[] { "Dev", "Eli" };.
Length, indeksowanie i ostatni element
Indeksy biegną od 0 do Length - 1. Length to właściwość, więc nie ma nawiasów (w przeciwieństwie do metody Count() z LINQ).
Wynik:
Count: 5
First: 18
Last: 16
Caught IndexOutOfRangeException
Odczyt lub zapis poza zakresem rzuca IndexOutOfRangeException w czasie działania programu; kompilator tego nie wyłapie. Zwykła przyczyna to warunek pętli zapisany jako i <= arr.Length zamiast i < arr.Length.
C# 8 i nowsze wersje dodają indeksy liczone od końca i zakresy, co skraca zapis ostatniego elementu i wycinków:
int last = temps[^1]; // 16
int[] middle = temps[1..4]; // { 21, 25, 19 }, a new array
Przechodzenie pętlą po tablicy
Pętla for daje ci indeks; foreach daje każdy element i jest czytelniejszym wyborem, gdy tylko odczytujesz.
Wynik:
4.95 | 13.20 | 3.58
Total: 21.73
Zmienna foreach jest tylko do odczytu: p = 0; wewnątrz pętli to błąd kompilacji. Żeby zmieniać elementy, użyj pętli z indeksem.
Sortowanie, odwracanie i wyszukiwanie
Metody pomocnicze są w statycznej klasie Array. Array.Sort sortuje w miejscu i nic nie zwraca, więc pierwotna kolejność przepada.
Wynik:
Ascending: 60, 72, 79, 88, 95
Descending: 95, 88, 79, 72, 60
Index of 60: 4
Index of 99: -1
Any above 90: True
First below 75: 72
Ana, ben, chloe
fig, kiwi, banana
Array.IndexOf zwraca -1, gdy wartości brakuje. Array.Find zwraca wartość domyślną typu (tutaj 0), gdy nic nie pasuje, co przy liczbach jest niejednoznaczne; gdy ma to znaczenie, użyj Array.FindIndex. Sortowanie malejące w jednym wywołaniu to Array.Sort(scores, (a, b) => b.CompareTo(a)).
Jeśli potrzebujesz posortowanego wyniku bez ruszania oryginału, LINQ zwraca nową tablicę: var sorted = scores.OrderBy(s => s).ToArray();. Zobacz LINQ.
Zmiana rozmiaru: tablica nie może urosnąć
Długość jest stała. Array.Resize tworzy nową tablicę o żądanym rozmiarze, kopiuje elementy i aktualizuje zmienną przekazaną przez ref.
Wynik:
4
2
True
False
Każda zmiana rozmiaru kopiuje wszystkie elementy. Powiększanie tablicy o jeden element w pętli jest wolne i to dokładnie to, co List<T> robi za ciebie wydajniej, podwajając swoją wewnętrzną tablicę.
Tablice to typy referencyjne: kopiowanie
Przypisanie tablicy do innej zmiennej kopiuje referencję, a nie elementy. Obie nazwy wskazują wtedy tę samą tablicę.
Wynik:
100
2
0, 100, 2, 3, 0
To samo dotyczy przekazania tablicy do metody: metoda może zmienić elementy należące do kodu wywołującego. Clone, Array.Copy, CopyTo i ToArray() z LINQ tworzą płytką kopię. W tablicy obiektów nowa tablica przechowuje referencje do tych samych obiektów, więc zmiana copy[0].Name nadal zmienia to, co widzi original[0].
Porównanie tablic przez == porównuje referencje. Żeby porównać zawartość, użyj a.SequenceEqual(b) z System.Linq.
Tablice 2D (wielowymiarowe)
Prostokątną siatkę deklaruje się z przecinkiem w nawiasach kwadratowych. Indeksuje się ją przez [row, col].
Wynik:
Rows: 2
Cols: 3
Length: 6, Rank: 2
. X .
. . X
Length w tablicy 2D to łączna liczba elementów (6 dla siatki 2 na 3), dlatego zagnieżdżone pętle używają GetLength(0) i GetLength(1). Rank to liczba wymiarów. Trzy wymiary działają tak samo: new int[4, 4, 4] i cube[x, y, z]. foreach po tablicy 2D odwiedza każdy element wiersz po wierszu.
Tablice postrzępione (tablice tablic)
Tablica postrzępiona int[][] to tablica, której elementy same są tablicami, a każda wewnętrzna tablica może mieć własną długość. Pasuje do danych w rodzaju "zamówienia na klienta", gdzie wiersze mają różne rozmiary.
Wynik:
Customer 0: 2 orders, 20, 35
Customer 1: 1 orders, 12
Customer 2: 4 orders, 8, 15, 40, 22
True
new int[3][] tworzy tylko zewnętrzną tablicę; każdy wiersz zaczyna jako null, a orders[0][0] przed przypisaniem wiersza rzuca NullReferenceException. Składnia new int[3][4] jest niedozwolona; każdy wiersz tworzysz sam.
Używaj [,] dla prawdziwej siatki (plansza, macierz, piksele), a [][], gdy wiersze mają różne długości albo chcesz podmieniać całe wiersze.
Tablica a List
Tablica T[] | List<T> | |
|---|---|---|
| Rozmiar | Ustalony przy tworzeniu | Rośnie i maleje |
| Liczba elementów | Właściwość Length | Właściwość Count |
| Dodawanie lub usuwanie | Niemożliwe (tylko Array.Resize) | Add, Insert, Remove |
| Wielowymiarowość | [,] i [][] | Tylko listy list |
| Typowe użycie | Znany rozmiar, tablice wyszukiwania, bufory | Zmieniające się kolekcje |
Konwersja w obie strony to jedno wywołanie: new List<int>(arr) albo arr.ToList() oraz list.ToArray(). List<T> to wersja, która może rosnąć.
Częste błędy
i <= arr.Lengthw pętli. Ostatni poprawny indeks toLength - 1; taki warunek rzucaIndexOutOfRangeException.- Wypisywanie tablicy bezpośrednio.
Console.WriteLine(arr)wypisujeSystem.Int32[]; użyjstring.Join. - Oczekiwanie, że
Array.Sortzwróci posortowaną tablicę. Zwracavoidi sortuje w miejscu. - Kopiowanie przez
=. To kopiuje referencję; użyjClone()lubToArray(). - Używanie wierszy tablicy postrzępionej przed ich utworzeniem. Każdy wiersz
new T[n][]jestnull, dopóki go nie przypiszesz. - Używanie
Lengthdo liczenia wierszy tablicy 2D. Liczy każdy element; użyjGetLength(0).
Najczęściej zadawane pytania
Jak sprawdzić długość tablicy w C#?
Użyj właściwości Length: scores.Length. To właściwość, a nie metoda, więc nie ma nawiasów. W tablicy 2D Length to łączna liczba elementów; liczbę wierszy daje GetLength(0), a liczbę kolumn GetLength(1).
Jak posortować tablicę w C#?
Array.Sort(arr) sortuje tablicę w miejscu, rosnąco. Żeby sortować malejąco, wywołaj Array.Reverse(arr) po sortowaniu albo przekaż porównanie: Array.Sort(arr, (a, b) => b.CompareTo(a)). Żeby dostać posortowaną kopię i zachować oryginał, użyj LINQ: arr.OrderBy(x => x).ToArray().
Czym różni się tablica 2D od tablicy postrzępionej w C#?
Tablica 2D int[,] to jeden prostokątny blok: każdy wiersz ma tyle samo kolumn, a indeksujesz ją jako grid[row, col]. Tablica postrzępiona int[][] to tablica tablic: każdy wiersz jest osobną tablicą o własnej długości, a indeksujesz ją jako rows[i][j]. Każdy wiersz tablicy postrzępionej trzeba utworzyć przed użyciem, inaczej jest null.
Czy można zmienić rozmiar tablicy w C#?
Nie. Długość tablicy jest ustalana przy jej tworzeniu. Array.Resize(ref arr, newSize) wygląda, jakby zmieniało rozmiar, ale tak naprawdę alokuje nową tablicę, kopiuje elementy i ustawia twoją zmienną na nową tablicę. Jeśli rozmiar często się zmienia, użyj List<T>.
Dlaczego wypisanie tablicy pokazuje System.Int32[]?
Console.WriteLine(arr) wywołuje arr.ToString(), a tablice tej metody nie nadpisują, więc dostajesz nazwę typu. Zamiast tego połącz elementy w jeden napis: Console.WriteLine(string.Join(", ", arr)).
Tablica czy List w C#?
Używaj tablicy, gdy liczba elementów jest znana i stała, na przykład 12 miesięcy albo plansza do gry. Używaj List<T>, gdy elementy z czasem dochodzą lub znikają. Obie struktury indeksują w stałym czasie, a List<T> przechowuje elementy wewnętrznie w tablicy.