Коллекции

Список List<T>

Последнее обновление: 19.11.2023

Хотя в языке C# есть массивы, которые хранят в себе наборы однотипных объектов, но работать с ними не всегда удобно. Например, массив хранит фиксированное количество объектов, однако что если мы заранее не знаем, сколько нам потребуется объектов. И в этом случае намного удобнее применять коллекции. Еще один плюс коллекций состоит в том, что некоторые из них реализует стандартные структуры данных, например, стек, очередь, словарь, которые могут пригодиться для решения различных специальных задач. Большая часть классов коллекций содержится в пространстве имен System.Collections.Generic.

Класс List<T> из пространства имен System.Collections.Generic представляет простейший список однотипных объектов. Класс List типизируется типом, объекты которого будут хранится в списке.

Мы можем создать пустой список:

List<string> people = new List<string>();

В данном случае объект List типизируется типом string. А это значит, что хранить в этом списке мы можем только строки.

Можно сразу при создании списка инициализировать его начальными значениями. В этом случае элементы списка помещаются после вызова конструктора в фигурных скобках

List<string> people = new List<string>() { "Tom", "Bob", "Sam" };

В данном случае в список помещаются три строки

Также можно при создании списка инициализировать его элементами из другой коллекции, например, другого списка:

var people = new List<string>() { "Tom", "Bob", "Sam" };
var employees = new List<string>(people);

Можно совместить оба способа:

var people = new List<string>() { "Tom", "Bob", "Sam" };
var employees = new List<string>(people){"Mike"};

В данном случае в списке employees будет четыре элемента ({ "Tom", "Bob", "Sam", "Mike" }) - три добавляются из списка people и один элемент задается при инициализации.

Начиная с версии C# 12 для определения списков можно использовать выражения коллекций, которые предполагают заключение элементов коллекции в квадратные скобки:

List<string> people = ["Tom", "Bob", "Sam"];
List<string> employees = [];// пустой список

Подобным образом можно работать со списками других типов, например:

List<Person> people = new List<Person>() 
{ 
    new Person("Tom"),
    new Person("Bob"), 
    new Person("Sam") 
};

class Person
{
    public string Name { get;}
    public Person(string name) => Name = name;
}

Установка начальной емкости списка

Еще один конструктор класса List принимает в качестве параметра начальную емкость списка:

List<string> people = new List<string>(16);

Указание начальной емкости списка позволяет в будущем увеличить производительность и уменьшить издержки на выделение памяти при добавлении элементов. Поскольку динамическое добавление в список может приводить на низком уровне к дополнительному выделению памяти, что снижает производительность. Если же мы знаем, что список не будет превышать некоторый размер, то мы можем передать этот размер в качестве емкости списка и избежать дополнительных выделений памяти.

Также начальную емкость можно установить с помощью свойства Capacity, которое имеется у класса List.

Обращение к элементам списка

Как и массивы, списки поддерживают индексы, с помощью которых можно обратиться к определенным элементам:

var people = new List<string>() { "Tom", "Bob", "Sam" };

string firstPerson = people[0];	// получаем первый элемент
Console.WriteLine(firstPerson); // Tom
people[0] = "Mike";		// изменяем первый элемент
Console.WriteLine(people[0]); // Mike

Длина списка

С помощью свойства Count можно получить длину списка:

var people = new List<string>() { "Tom", "Bob", "Sam" };
Console.WriteLine(people.Count);    // 3

Перебор списка

C# позволяет осуществить перебор списка с помощью стандартного цикла foreach:/p>

var people = new List<string>() { "Tom", "Bob", "Sam" };

foreach (var person in people)
{
    Console.WriteLine(person);
}
// Вывод программы:
// Tom
// Bob
// Sam

Также можно использовать другие типы циклов и в комбинации с индексами перебирать списки:

var people = new List<string>() { "Tom", "Bob", "Sam" };

for (int i = 0; i < people.Count; i++)
{
    Console.WriteLine(people[i]);
}

Методы списка

Среди его методов можно выделить следующие:

  • void Add(T item): добавление нового элемента в список

  • void AddRange(IEnumerable<T> collection): добавление в список коллекции или массива

  • int BinarySearch(T item): бинарный поиск элемента в списке. Если элемент найден, то метод возвращает индекс этого элемента в коллекции. При этом список должен быть отсортирован.

  • void CopyTo(T[] array): копирует список в массив array

  • void CopyTo(int index, T[] array, int arrayIndex, int count): копирует из списка начиная с индекса index элементы, количество которых равно count, и вставляет их в массив array начиная с индекса arrayIndex

  • bool Contains(T item): возвращает true, если элемент item есть в списке

  • void Clear(): удаляет из списка все элементы

  • bool Exists(Predicate<T> match): возвращает true, если в списке есть элемент, который соответствует делегату match

  • T? Find(Predicate<T> match): возвращает первый элемент, который соответствует делегату match. Если элемент не найден, возвращается null

  • T? FindLast(Predicate<T> match): возвращает последний элемент, который соответствует делегату match. Если элемент не найден, возвращается null

  • List<T> FindAll(Predicate<T> match): возвращает список элементов, которые соответствуют делегату match

  • int IndexOf(T item): возвращает индекс первого вхождения элемента в списке

  • int LastIndexOf(T item): возвращает индекс последнего вхождения элемента в списке

  • List<T> GetRange(int index, int count): возвращает список элементов, количество которых равно count, начиная с индекса index.

  • void Insert(int index, T item): вставляет элемент item в список по индексу index. Если такого индекса в списке нет, то генерируется исключение

  • void InsertRange(int index, collection): вставляет коллекцию элементов collection в текущий список начиная с индекса index. Если такого индекса в списке нет, то генерируется исключение

  • bool Remove(T item): удаляет элемент item из списка, и если удаление прошло успешно, то возвращает true. Если в списке несколько одинаковых элементов, то удаляется только первый из них

  • void RemoveAt(int index): удаление элемента по указанному индексу index. Если такого индекса в списке нет, то генерируется исключение

  • void RemoveRange(int index, int count): параметр index задает индекс, с которого надо удалить элементы, а параметр count задает количество удаляемых элементов.

  • int RemoveAll((Predicate<T> match)): удаляет все элементы, которые соответствуют делегату match. Возвращает количество удаленных элементов

  • void Reverse(): изменяет порядок элементов

  • void Reverse(int index, int count): изменяет порядок на обратный для элементов, количество которых равно count, начиная с индекса index

  • void Sort(): сортировка списка

  • void Sort(IComparer<T>? comparer): сортировка списка с помощью объекта comparer, который передается в качестве параметра

Добавление в список

List<string> people = new List<string> () { "Tom" };

people.Add("Bob"); // добавление элемента
// people = { "Tom", "Bob" };

people.AddRange(new[] { "Sam", "Alice" });   // добавляем массив
// people = { "Tom", "Bob", "Sam", "Alice" };
// также можно было бы добавить другой список
// people.AddRange(new List<string>(){ "Sam", "Alice" });

people.Insert(0, "Eugene"); // вставляем на первое место
// people = { "Eugene", "Tom", "Bob", "Sam", "Alice" };

people.InsertRange(1, new string[] {"Mike", "Kate"}); // вставляем массив с индекса 1
// people = { "Eugene", "Mike", "Kate", "Tom", "Bob", "Sam", "Alice" };

// также можно было бы добавить другой список
// people.InsertRange(1, new List<string>(){ "Mike", "Kate" });

Удаление из списка

var people = new List<string> () { "Eugene", "Mike", "Kate", "Tom", "Bob", "Sam", "Tom", "Alice" };

people.RemoveAt(1); //  удаляем второй элемент
// people = { "Eugene", "Kate", "Tom", "Bob", "Sam", "Tom", "Alice" };

people.Remove("Tom"); //  удаляем элемент "Tom"
// people = { "Eugene", "Kate", "Bob", "Sam", "Tom", "Alice" };

// удаляем из списка все элементы, длина строки которых равна 3
people.RemoveAll(person => person.Length == 3);
// people = { "Eugene", "Kate", "Alice" };

// удаляем из списка 2 элемента начиная с индекса 1
people.RemoveRange(1, 2);
// people = { "Eugene"};

// полностью очищаем список
people.Clear();
// people = {  };

Поиск и проверка элемента

var people = new List<string> () { "Eugene", "Mike", "Kate", "Tom", "Bob", "Sam" };

var containsBob = people.Contains("Bob");     //  true
var containsBill = people.Contains("Bill");    // false

// проверяем, есть ли в списке строки с длиной 3 символа
var existsLength3 = people.Exists(p => p.Length == 3);  // true

// проверяем, есть ли в списке строки с длиной 7 символов
var existsLength7 = people.Exists(p => p.Length == 7);  // false

// получаем первый элемент с длиной в 3 символа
var firstWithLength3 = people.Find(p => p.Length == 3); // Tom

// получаем последний элемент с длиной в 3 символа
var lastWithLength3 = people.FindLast(p => p.Length == 3);  // Sam

// получаем все элементы с длиной в 3 символа в виде списка
List<string> peopleWithLength3 = people.FindAll(p => p.Length == 3);
// peopleWithLength3 { "Tom", "Bob", "Sam"}

Получение диапазона и копирование в массив

List<string> people = new List<string>() {"Eugene", "Tom", "Mike", "Sam", "Bob" };

// получаем диапазон со второго по четвертый элемент
var range = people.GetRange(1, 3);
// range = { "Tom", "Mike", "Sam"};

// копируем в массив первые три элемента
string[] partOfPeople = new string[3];
people.CopyTo(0, partOfPeople, 0, 3);
// partOfPeople = { "Eugene", "Tom", "Mike"};

Расположение элементов в обратном порядке

var people = new List<string> () { "Eugene", "Tom", "Mike", "Sam", "Bob" };

// переворачиваем весь список
people.Reverse();
// people = { "Bob","Sam", "Mike", "Tom", "Eugene"};

var people2 = new List<string>() { "Eugene", "Tom", "Mike", "Sam", "Bob" };
// переворачиваем часть только 3 элемента с индекса 1
people2.Reverse(1, 3);
// people2 = { "Eugene","Sam", "Mike", "Tom", "Bob" };
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850