Что такое индексы в C#? Какие типы индексов существуют и использовали ли вы их на практике?
Answer from AI
sobes.tech AI
Индексаторы в C# позволяют обращаться к экземпляру класса или структуры как к массиву, используя синтаксис []. Они не статичны и перегружают оператор [].
Индексаторы
Индексаторы позволяют определять логику доступа к элементам коллекции или структуре данных внутри класса.
public class MyCollection
{
private string[] data = new string[10];
// Индексатор, позволяющий получать или устанавливать элемент по индексу
public string this[int index]
{
get
{
// Проверка границ
if (index >= 0 && index < data.Length)
{
return data[index];
}
else
{
throw new IndexOutOfRangeException();
}
}
set
{
// Проверка границ
if (index >= 0 && index < data.Length)
{
data[index] = value;
}
else
{
throw new IndexOutOfRangeException();
}
}
}
}
Типы параметров индексаторов
Индексаторы могут принимать любое количество параметров любого типа, не ограничиваясь только целочисленными типами.
public class DictionaryLike
{
private Dictionary<string, string> _dictionary = new Dictionary<string, string>();
// Индексатор с параметром типа string
public string this[string key]
{
get
{
if (_dictionary.ContainsKey(key))
{
return _dictionary[key];
}
else
{
return null; // Или выбросить исключение
}
}
set
{
_dictionary[key] = value;
}
}
}
Перегрузка индексаторов
Можно создавать перегруженные индексаторы с различными сигнатурами (набором и типами параметров).
public class Matrix
{
private int[,] data;
public Matrix(int rows, int cols)
{
data = new int[rows, cols];
}
// Индексатор с двумя целочисленными параметрами
public int this[int row, int col]
{
get
{
// Проверка границ
if (row >= 0 && row < data.GetLength(0) && col >= 0 && col < data.GetLength(1))
{
return data[row, col];
}
else
{
throw new IndexOutOfRangeException();
}
}
set
{
// Проверка границ
if (row >= 0 && row < data.GetLength(0) && col >= 0 && col < data.GetLength(1))
{
data[row, col] = value;
}
else
{
throw new IndexOutOfRangeException();
}
}
}
}
Диапазонные индексы (Ranges & Indices)
В C# 8.0 были введены новые типы System.Index и System.Range, которые позволяют использовать синтаксис для обращения к элементам с конца коллекции (^) и для получения поддиапазона (..). Эти понятия часто называют "индексами", но они отличаются от классических индексаторов.
using System;
public class ArrayExample
{
public static void Main(string[] args)
{
string[] words = { "the", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog" };
// Использование System.Index для доступа с конца
Index last = ^1; // Индекс последнего элемента
Console.WriteLine(words[last]); // dog
// Использование System.Range для получения поддиапазона
Range middle = 1..4; // Элементы с индекса 1 до (но не включая) индекса 4
string[] subset = words[middle]; // {"quick", "brown", "fox"}
// Range с использованием System.Index
Range fromEnd = ^3..; // от третьего с конца до конца
string[] suffix = words[fromEnd]; // {"the", "lazy", "dog"}
}
}
Применение на практике
Я активно использовал индексаторы при создании собственных классов коллекций или оберток над существующими для предоставления более интуитивного доступа к данным. Например:
- Разработка классов, представляющих матрицы или многомерные данные, где доступ по координатам
matrix[row, col]был логичен. - Создание оберток над
Dictionary<>или другими коллекциями, где доступ по ключу через индексатор улучшал читаемость кода. - В простых коллекциях, где требовалось синтаксическое удобство доступа, подобное массиву.
Диапазонные индексы (System.Index и System.Range) использовал для более лаконичного доступа к частям массивов или списков, что особенно полезно при работе с подстроками или частичными данными из коллекции.