Sobes.tech
Junior
113
questionbank

Что такое индексы в 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) использовал для более лаконичного доступа к частям массивов или списков, что особенно полезно при работе с подстроками или частичными данными из коллекции.