Что такое индексатор?csharp-82

Индексатор — это специальный член класса, который позволяет обращаться к элементам объекта как к элементам массива, используя синтаксис квадратных скобок []. Это мощный инструмент для создания коллекций или классов, которые должны предоставлять индексированный доступ к своим данным.

Основные характеристики индексаторов

  1. Синтаксис:
    • Использует ключевое слово this для определения
    • Может принимать один или несколько параметров
    • Может быть перегружен
public class MyCollection
{
    private string[] items = new string[10];

    // Индексатор с целочисленным параметром
    public string this[int index]
    {
        get => items[index];
        set => items[index] = value;
    }
}
  1. Использование:
    • Позволяет использовать объект как массив
var collection = new MyCollection();
collection[0] = "First";  // Установка значения через индексатор
string item = collection[0];  // Получение значения

Особенности индексаторов

  1. Параметры:
    • Могут быть любого типа (не только int)
    • Может быть несколько параметров (например, для матриц)
public class Matrix
{
    private double[,] data = new double[10, 10];

    public double this[int row, int column]
    {
        get => data[row, column];
        set => data[row, column] = value;
    }
}
  1. Модификаторы доступа:
    • Можно задавать разные модификаторы для get/set
    • Могут быть виртуальными, абстрактными или переопределенными
public virtual string this[int index]
{
    protected get { /* ... */ }
    set { /* ... */ }
}

Отличия от свойств и методов

ХарактеристикаИндексаторСвойствоМетод
Синтаксис вызоваobj[index]obj.Propertyobj.Method()
ИмяthisЛюбое имяЛюбое имя
ПараметрыОбязательныНетОпциональны
НазначениеИндексированный доступДоступ к состояниюВыполнение действий

Продвинутые сценарии использования

  1. Словарный доступ:
public class Config
{
    private Dictionary<string, string> settings = new();

    public string this[string key]
    {
        get => settings.TryGetValue(key, out var value) ? value : null;
        set => settings[key] = value;
    }
}
  1. Ленивая загрузка данных:
public class LazyLoader
{
    public Data this[int id] => LoadData(id);

    private Data LoadData(int id) { /* ... */ }
}
  1. Перегрузка индексаторов:
public class MultiIndex
{
    public string this[int index] { /* ... */ }
    public string this[string name] { /* ... */ }
}

Лучшие практики

  1. Генерировать исключения при недопустимых индексах:
public string this[int index]
{
    get
    {
        if (index < 0 || index >= items.Length)
            throw new IndexOutOfRangeException();
        return items[index];
    }
}
  1. Избегать сложной логики в индексаторах
  2. Документировать ожидаемое поведение

Резюмируем:

индексаторы — это удобный синтаксический сахар, который позволяет создавать классы с семантикой массива. Они особенно полезны для реализации коллекций, контейнеров данных и классов, которые должны предоставлять индексированный доступ к своим элементам.