Индексы и диапазоны

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

В C# 8.0 была добавлена новая функциональность - индексы и диапазоны, которые упрощают получение из массивов подмассивов. Для этого в C# есть два типа: System.Range и System.Index. Оба типа являются структурами. Тип Range представляет некоторый диапазон значений в некоторой последовательность, а тип Index - индекс в последовательности.

Индексы

Индекс фактически представляет числовое значение, и при определении индекса мы можем указать это значение:

Index myIndex = 2;

В данном случае индекс представляет третий элемент последовательности (индексация начинается с 0).

С помощью специального оператора ^ можно задать индекс относительно конца последовательности.

Index myIndex = ^2;

Теперь индекс представляет второй элемент с конца последовательности, то есть предпоследний элемент.

Используем индексы для получения элементов массива:

Index myIndex1 = 2;		// третий элемент
Index myIndex2 = ^2;	// предпоследний элемент

string[] people = { "Tom", "Bob", "Sam", "Kate", "Alice" };
string selected1 = people[myIndex1];    // Sam
string selected2 = people[myIndex2];    // Kate
Console.WriteLine(selected1);   
Console.WriteLine(selected2);

Фактически для данной задачи индексы не нужны, и мы можем воспользоваться стандартными возможностями массивов:

string[] people = { "Tom", "Bob", "Sam", "Kate", "Alice" };
string selected1 = people[2];    // Sam
string selected2 = people[people.Length - 2];    // Kate
Console.WriteLine(selected1);   
Console.WriteLine(selected2);

То есть в подобных ситуациях плюсом индексов является большая удобочитаемость. Так, people[^2] более читабельно, чем people[people.Length - 2].

Диапазон

Диапазон представляет часть последовательности, которая ограничена двумя индексами. Начальный индекс включается в диапазон, а конечный индекс НЕ входит в диапазон. Для определения диапазона применяется оператор ..:

Range myRange1 = 1..4; // по 1-го индекса включая по 4-й индекс не включая

В данном случае диапазон myRange1 включает элементы с 1 индекса по 4-й индекс (не включая). При этом элемент по 4-му индексу не включается в диапазон. При этом границы диапазона задаются не просто числами, а именно объектами Index. То есть следующие определения диапазонов будут равноценны:

Index start = 1;
Index end = 4;
Range myRange1 = start..end;
			
Range myRange2 = 1..4;

Практическое применение диапазонов - получим со второго по четвертый элементы массива:

string[] people = { "Tom", "Bob", "Sam", "Kate", "Alice" };
string[] peopleRange = people[1..4]; // получаем 2, 3 и 4-й элементы из массива
foreach(var person in peopleRange)
{
	Console.WriteLine(person);
}

Результатом операции people[1..4] является подмассив элементов с 1 по 3 индексы (включая). Консольный вывод:

Bob
Sam
Kate

Мы можем задать для диапазона только конечный индекс. В этом случае начальным индексом по умолчанию будет 0.

string[] people = { "Tom", "Bob", "Sam", "Kate", "Alice" };
string[] peopleRange = people[..4];     // Tom, Bob, Sam, Kate

Либо, наоборот, задать только начальный индекс, тогда конечным индексом будет последний индекс последовательности:

string[] people = { "Tom", "Bob", "Sam", "Kate", "Alice" };
string[] peopleRange = people[1..];     // Bob, Sam, Kate, Alice

Используя индексы относительно конца последовательности, можно получать диапазон относительно конца последовательности:

string[] people = { "Tom", "Bob", "Sam", "Kate", "Alice" };
string[] peopleRange1 = people[^2..];     	// два последних - Kate, Alice
string[] peopleRange2 = people[..^1];   	// начиная с предпоследнего - Tom, Bob, Sam, Kate
string[] peopleRange3 = people[^3..^1];   	// два начиная с предпоследнего - Sam, Kate

Кроме массивов индексы и диапазоны также применяются к объектам Span и ReadOnlySpan:

string[] people = { "Tom", "Bob", "Sam", "Kate", "Alice" };
Span<string> peopleSpan = people;
Span<string> selectedPeopleSpan = peopleSpan[1..4];
foreach (var person in selectedPeopleSpan)
{
	Console.WriteLine(person);
}
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850