0Pricing
C# Academy · Урок

Списки на практике

Добавляйте, удаляйте и ищите элементы.

«Списки на практике» — бесплатный урок 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 — локальная установка не требуется.

Все уроки этого курса

  1. Списки на практике
  2. Поиск в словарях
  3. HashSet и уникальность
  4. Выбор коллекции
← Назад к C# Academy