Списки на практике
Добавляйте, удаляйте и ищите элементы.
«Списки на практике» — бесплатный урок C# Academy на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения C# Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс C# Academy содержит 4 уроков всего.
Зачем нужен List<T>?
List<T> — это повседневный динамический массив в C#. Он находится в System.Collections.Generic и автоматически увеличивается при добавлении элементов.
В отличие от обычного массива, Вам не нужно заранее задавать фиксированный размер. Этот тип безопасен: List<int> содержит только значения типа int, что проверяется во время компиляции.
using System.Collections.Generic;
List<int> scores = new List<int>();
scores.Add(90);
scores.Add(85);Создание и инициализация
Заполнить список сразу можно с помощью инициализатора коллекции. Такой способ краток и понятен.
Компилятор преобразует каждую запись в вызов Add, поэтому результат идентичен добавлению элементов по одному.
using System;
using System.Collections.Generic;
class Program {
static void Main() {
var fruits = new List<string> { "apple", "pear", "plum" };
Console.WriteLine(fruits.Count);
}
}Индексация и количество элементов
Получайте доступ к элементам по индексу, отсчитываемому от нуля, как в массиве. list[0] — первый элемент.
Используйте Count, а не Length, чтобы узнать, сколько элементов содержит список. Чтение или запись по индексу выполняется за постоянное время O(1).
using System;
using System.Collections.Generic;
class Program {
static void Main() {
var nums = new List<int> { 10, 20, 30 };
Console.WriteLine(nums[1]);
Console.WriteLine(nums.Count);
}
}Добавление и вставка
Add добавляет элемент в конец за амортизированное время O(1). AddRange добавляет сразу много элементов.
Insert(index, item) помещает элемент в указанную позицию, сдвигая все последующие. Из-за этого вставка Insert в начало занимает O(n), поэтому по возможности добавляйте элементы в конец.
var list = new List<string> { "b", "c" };
list.Insert(0, "a");
list.AddRange(new[] { "d", "e" });
// list is now a, b, c, d, eУдаление элементов
Remove(item) удаляет первое совпадающее значение и возвращает true, если оно найдено. RemoveAt(index) удаляет элемент по позиции.
Обе операции сдвигают последующие элементы влево, поэтому удаление из середины занимает O(n). RemoveAll принимает условие и удаляет все совпадения за один проход.
using System;
using System.Collections.Generic;
class Program {
static void Main() {
var nums = new List<int> { 1, 2, 3, 4, 5 };
nums.RemoveAll(n => n % 2 == 0);
Console.WriteLine(string.Join(",", nums));
}
}Поиск в списке
Contains сообщает, существует ли значение; IndexOf возвращает его позицию или -1. Оба метода выполняют линейный поиск за O(n).
Если Вам приходится многократно искать значения в большом списке, затраты на линейный поиск накапливаются. В таком случае лучше подойдут HashSet или Dictionary.
var names = new List<string> { "Ann", "Bob", "Cy" };
bool hasBob = names.Contains("Bob"); // true
int pos = names.IndexOf("Cy"); // 2Перебор элементов
Цикл foreach — самый понятный способ прочитать каждый элемент. Также можно использовать обычный цикл for, если нужен индекс.
Не добавляйте и не удаляйте элементы внутри foreach, выполняющегося для того же списка: это вызовет InvalidOperationException.
using System;
using System.Collections.Generic;
class Program {
static void Main() {
var colors = new List<string> { "red", "green", "blue" };
foreach (var c in colors)
Console.WriteLine(c);
}
}Сортировка
Sort() сортирует список на месте с помощью компаратора по умолчанию. Чтобы задать собственный порядок, передайте делегат сравнения.
Сортировка выполняется за O(n log n). Чтобы получить отсортированную копию, не изменяя исходный список, используйте OrderBy из LINQ: он возвращает новую последовательность.
using System;
using System.Collections.Generic;
class Program {
static void Main() {
var nums = new List<int> { 4, 1, 3, 2 };
nums.Sort();
Console.WriteLine(string.Join(",", nums));
}
}Ёмкость и количество элементов
Count — это количество существующих элементов, а Capacity — количество элементов, которое список может вместить до перераспределения внутреннего массива.
Когда список становится больше своей ёмкости, он выделяет больший массив и копирует элементы, обычно удваивая размер. Если известен окончательный размер, передайте его конструктору, чтобы избежать повторного копирования.
var list = new List<int>(1000); // reserve capacity
for (int i = 0; i < 1000; i++)
list.Add(i);
// no intermediate reallocationsСписок как аргумент метода
List<T> — ссылочный тип. При передаче списка в метод передаётся ссылка, поэтому изменения внутри метода влияют на список вызывающего кода.
Если метод только читает данные, принимайте IEnumerable<T> или IReadOnlyList<T>, чтобы показать, что Вы не будете изменять список.
using System;
using System.Collections.Generic;
class Program {
static void AddOne(List<int> xs) => xs.Add(1);
static void Main() {
var nums = new List<int>();
AddOne(nums);
Console.WriteLine(nums.Count); // 1
}
}Преобразование и копирование
ToArray() создаёт массив фиксированного размера, а new List<T>(other) — поверхностную копию другой последовательности.
Поверхностная копия дублирует структуру списка, но использует те же ссылки на элементы, поэтому изменение содержащегося объекта видно через оба списка.
var original = new List<int> { 1, 2, 3 };
int[] arr = original.ToArray();
var copy = new List<int>(original);Быстрая проверка
Выберите операцию, стоимость которой заметно выше остальных.
Итоги
List<T> — это расширяемый массив с проверкой типов. Доступ по индексу и Count выполняются за O(1), а добавление в конец с амортизацией занимает O(1).
Вставка, удаление и поиск значения в середине занимают O(n) из-за сдвига или последовательного просмотра. Если размер известен заранее, задайте ёмкость, чтобы избежать перераспределений.
Часто задаваемые вопросы
Урок «Списки на практике» бесплатный?
Да — полный текст урока «Списки на практике» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс C# Academy, подпишись на CoddyKit PRO. Курс C# Academy содержит 4 уроков всего.
Чему я научусь в уроке «Списки на практике»?
Добавляйте, удаляйте и ищите элементы. Ты практикуешь C# Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать C# Academy?
Предыдущий опыт не требуется. C# Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.
Сколько времени занимает урок «Списки на практике»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке C# Academy?
Да. Каждый урок C# Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Списки на практике
- Поиск в словарях
- HashSet и уникальность
- Выбор коллекции