Menu

Tablice w C#: deklaracja, Length, sortowanie, tablice 2D i postrzępione

Tablica w C# to blok elementów jednego typu o stałym rozmiarze. Dowiedz się, jak deklarować i inicjalizować tablice, odczytywać Length, sortować i przeszukiwać je klasą Array, bezpiecznie je kopiować oraz pracować z tablicami 2D i postrzępionymi.

Na tej stronie są działające edytory: edytuj, uruchamiaj i od razu zobacz wynik.

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>
RozmiarUstalony przy tworzeniuRośnie i maleje
Liczba elementówWłaściwość LengthWłaściwość Count
Dodawanie lub usuwanieNiemożliwe (tylko Array.Resize)Add, Insert, Remove
Wielowymiarowość[,] i [][]Tylko listy list
Typowe użycieZnany rozmiar, tablice wyszukiwania, buforyZmieniają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.Length w pętli. Ostatni poprawny indeks to Length - 1; taki warunek rzuca IndexOutOfRangeException.
  • Wypisywanie tablicy bezpośrednio. Console.WriteLine(arr) wypisuje System.Int32[]; użyj string.Join.
  • Oczekiwanie, że Array.Sort zwróci posortowaną tablicę. Zwraca void i sortuje w miejscu.
  • Kopiowanie przez =. To kopiuje referencję; użyj Clone() lub ToArray().
  • Używanie wierszy tablicy postrzępionej przed ich utworzeniem. Każdy wiersz new T[n][] jest null, dopóki go nie przypiszesz.
  • Używanie Length do liczenia wierszy tablicy 2D. Liczy każdy element; użyj GetLength(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.

Ilustracja języków programowania w Coddy

Ucz się programowania z Coddy

ZACZNIJ