This lesson is not translated yet – the Russian original is below.
Массив – самая простая коллекция: несколько значений одного типа, лежащих в памяти подряд. Все остальные коллекции устроены сложнее, но объясняются через него.
Объявление
Три способа записать одно и то же:
int[] a = new int[5]; // пять нулей
int[] b = new int[] { 1, 2, 3 }; // с указанием значений
int[] c = { 1, 2, 3 }; // короткая форма
Квадратные скобки идут после типа, а не после имени: int[] numbers, а не int numbers[], как
в C и Java.
Элементы заполняются автоматически: числа – нулями, bool – значением false, ссылочные типы – null. Это отличие от локальных переменных, которые компилятор требует присвоить вручную.
Обращение по индексу
int[] numbers = { 10, 20, 30 };
Console.WriteLine(numbers[0]); // 10 – первый
Console.WriteLine(numbers[2]); // 30 – последний
numbers[1] = 99; // запись
Нумерация с нуля, поэтому у массива из трёх элементов индексы 0, 1 и 2. Длина хранится в свойстве
Length:
Console.WriteLine(numbers.Length); // 3
Console.WriteLine(numbers[numbers.Length - 1]); // последний элемент
Выход за границы – это IndexOutOfRangeException во время работы, а не при компиляции. Компилятор не знает, каким будет индекс: он мог прийти от пользователя. Проверка происходит в рантайме, каждый раз – именно поэтому рантайм и гарантирует, что чужую память вы не прочитаете.
Индексы с конца
Писать numbers[numbers.Length - 1] неудобно, поэтому есть короткая запись:
Console.WriteLine(numbers[^1]); // последний
Console.WriteLine(numbers[^2]); // предпоследний
Знак ^ означает отсчёт с конца, причём ^1 – это именно последний элемент, а не выход за
границу: с конца счёт идёт с единицы, а с начала – с нуля.
Диапазон элементов берётся оператором ..:
int[] all = { 1, 2, 3, 4, 5 };
int[] middle = all[1..4]; // 2, 3, 4 – правая граница не включается
int[] head = all[..2]; // 1, 2
int[] tail = all[3..]; // 4, 5
Размер не меняется
Главное ограничение массива: длина задаётся при создании и остаётся навсегда. Добавить шестой элемент в массив из пяти невозможно – можно только создать новый массив и скопировать туда старое содержимое.
int[] bigger = new int[numbers.Length + 1];
Array.Copy(numbers, bigger, numbers.Length);
bigger[^1] = 40;
Делать так вручную приходится редко: для меняющегося набора данных есть List<T>, о нём следующий
урок. Массив берут, когда количество элементов известно заранее и не меняется.
Перебор
Оба способа вы уже знаете:
foreach (var number in numbers)
{
Console.WriteLine(number);
}
foreach – когда нужны все элементы подряд. for – когда нужен индекс или обход не с начала:
for (int i = numbers.Length - 1; i >= 0; i--)
{
Console.WriteLine(numbers[i]); // в обратном порядке
}
Что умеет класс Array
Готовые операции лежат в статическом классе Array:
int[] numbers = { 5, 3, 8, 1 };
Array.Sort(numbers); // 1, 3, 5, 8 – сортирует на месте
Array.Reverse(numbers); // 8, 5, 3, 1
int index = Array.IndexOf(numbers, 3); // 2, или -1 если не нашлось
Array.Sort меняет исходный массив, а не возвращает новый. Это частая ловушка: если исходный порядок ещё нужен, сначала сделайте копию через ToArray().
Полезные методы есть и у самого массива – они пришли из LINQ и работают со всеми коллекциями:
Console.WriteLine(numbers.Max());
Console.WriteLine(numbers.Min());
Console.WriteLine(numbers.Sum());
Console.WriteLine(numbers.Average());
Для них нужен using System.Linq; – в новых проектах он подключается автоматически.
Двумерные массивы
Таблица объявляется через запятую в скобках:
int[,] table = new int[3, 4]; // три строки, четыре столбца
table[0, 0] = 1;
table[2, 3] = 9;
Console.WriteLine(table.GetLength(0)); // 3 – строк
Console.WriteLine(table.GetLength(1)); // 4 – столбцов
У двумерного массива Length вернёт общее число ячеек (12), а не число строк – для размерностей
есть GetLength.
Существует и второй вид – массив массивов, где строки могут быть разной длины:
int[][] jagged = new int[3][];
jagged[0] = new int[] { 1, 2 };
jagged[1] = new int[] { 3, 4, 5 };
Различать их просто: [,] – прямоугольная таблица, [][] – набор независимых массивов. Первый
экономнее по памяти, второй гибче.