0Pricing
C# Academy · Урок

Индексаторы

Обращайтесь к объектам с помощью синтаксиса, похожего на работу с массивами.

«Индексаторы» — бесплатный урок C# Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения C# Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс C# Academy содержит 4 уроков всего.

Что такое индексатор

Индексатор позволяет обращаться к объекту с помощью синтаксиса [ ], как к массиву. Он определяется с помощью this[...]. Индексаторы идеально подходят для классов, похожих на коллекции.

using System;

class Week
{
    private string[] _days = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };

    public string this[int index] => _days[index];
}

class Program
{
    static void Main()
    {
        var w = new Week();
        Console.WriteLine(w[0]);
        Console.WriteLine(w[6]);
    }
}

Синтаксис индексатора

Индексатор похож на свойство, но использует this и принимает список параметров в квадратных скобках. Он содержит get и необязательный set.

using System;

class Scores
{
    private int[] _data = new int[5];

    public int this[int i]
    {
        get { return _data[i]; }
        set { _data[i] = value; }
    }
}

class Program
{
    static void Main()
    {
        var s = new Scores();
        s[0] = 90;
        s[1] = 75;
        Console.WriteLine(s[0] + ", " + s[1]);
    }
}

Чтение и запись через индексатор

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

using System;

class Grid
{
    private int[] _cells = new int[3];

    public int this[int i]
    {
        get => _cells[i];
        set => _cells[i] = value;
    }
}

class Program
{
    static void Main()
    {
        var g = new Grid();
        for (int i = 0; i < 3; i++) g[i] = i * 10;
        Console.WriteLine(g[0] + ", " + g[1] + ", " + g[2]);
    }
}

Проверка в индексаторе

Поскольку индексатор является обычным кодом, Вы можете проверить индекс и создать понятное исключение при обращении за пределами диапазона.

using System;

class SafeList
{
    private int[] _data = new int[3];

    public int this[int i]
    {
        get
        {
            if (i < 0 || i >= _data.Length)
                throw new IndexOutOfRangeException("Bad index: " + i);
            return _data[i];
        }
        set { _data[i] = value; }
    }
}

class Program
{
    static void Main()
    {
        var list = new SafeList();
        list[1] = 42;
        Console.WriteLine(list[1]);
    }
}

Индексаторы со строковыми ключами

Параметры индексатора не ограничены типом int. Ключ типа string превращает класс в средство поиска, похожее на словарь.

using System;
using System.Collections.Generic;

class Config
{
    private Dictionary<string, string> _map = new Dictionary<string, string>();

    public string this[string key]
    {
        get => _map.ContainsKey(key) ? _map[key] : "(none)";
        set => _map[key] = value;
    }
}

class Program
{
    static void Main()
    {
        var c = new Config();
        c["theme"] = "dark";
        Console.WriteLine(c["theme"]);
        Console.WriteLine(c["missing"]);
    }
}

Несколько параметров

Индексатор может принимать более одного параметра, что идеально подходит для матриц или двумерных сеток, к которым обращаются как к matrix[row, col].

using System;

class Matrix
{
    private int[,] _data = new int[2, 2];

    public int this[int row, int col]
    {
        get => _data[row, col];
        set => _data[row, col] = value;
    }
}

class Program
{
    static void Main()
    {
        var m = new Matrix();
        m[0, 0] = 1;
        m[1, 1] = 9;
        Console.WriteLine(m[0, 0] + ", " + m[1, 1]);
    }
}

Индексаторы только для чтения

Не указывайте метод записи, чтобы сделать индексатор доступным только для чтения и предоставить данные без возможности внешнего изменения.

using System;

class Fibonacci
{
    public int this[int n]
    {
        get
        {
            int a = 0, bv = 1;
            for (int i = 0; i < n; i++)
            {
                int t = a + bv;
                a = bv;
                bv = t;
            }
            return a;
        }
    }
}

class Program
{
    static void Main()
    {
        var fib = new Fibonacci();
        Console.WriteLine(fib[7]);
    }
}

Индексаторы и свойства

К свойству обращаются по имени (obj.Name), а к индексатору — по ключу (obj[key]). Используйте индексатор, когда объект ведёт себя как коллекция.

using System;

class Inventory
{
    private int[] _stock = new int[4];
    public int Total => _stock.Length;          // property
    public int this[int slot]                    // indexer
    {
        get => _stock[slot];
        set => _stock[slot] = value;
    }
}

class Program
{
    static void Main()
    {
        var inv = new Inventory();
        inv[2] = 15;
        Console.WriteLine("Slot 2: " + inv[2] + ", Total slots: " + inv.Total);
    }
}

Перегруженные индексаторы

Можно определить несколько индексаторов с разными типами параметров, и компилятор выберет подходящий.

using System;
using System.Collections.Generic;

class People
{
    private List<string> _names = new List<string> { "Ann", "Bob", "Cara" };

    public string this[int i] => _names[i];
    public int this[string name] => _names.IndexOf(name);
}

class Program
{
    static void Main()
    {
        var p = new People();
        Console.WriteLine(p[1]);
        Console.WriteLine(p["Cara"]);
    }
}

Перебор индексированного объекта

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

using System;

class Ring
{
    private int[] _data = { 10, 20, 30 };
    public int Count => _data.Length;
    public int this[int i] => _data[i % _data.Length];
}

class Program
{
    static void Main()
    {
        var ring = new Ring();
        for (int i = 0; i < 5; i++)
            Console.Write(ring[i] + " ");
        Console.WriteLine();
    }
}

Объединение всего изученного

Индексаторы придают классам-обёрткам вид обычных коллекций, скрывая детали хранения за привычным синтаксисом квадратных скобок.

using System;
using System.Collections.Generic;

class Phonebook
{
    private Dictionary<string, string> _book = new Dictionary<string, string>();

    public string this[string name]
    {
        get => _book.TryGetValue(name, out var num) ? num : "unknown";
        set => _book[name] = value;
    }
}

class Program
{
    static void Main()
    {
        var pb = new Phonebook();
        pb["Alice"] = "555-1234";
        Console.WriteLine("Alice: " + pb["Alice"]);
        Console.WriteLine("Zed: " + pb["Zed"]);
    }
}

Быстрая проверка

Проверьте, насколько хорошо Вы поняли индексаторы.

Итоги

Индексатор использует this[...], чтобы предоставить классу доступ, похожий на доступ к массиву. Он поддерживает get/set, параметры любых типов (int, string и несколько параметров), проверку, перегрузку и варианты только для чтения. Используйте индексаторы для классов, похожих на коллекции, а именованные свойства — для отдельных атрибутов.

using System;

class Demo
{
    private int[] _v = new int[3];
    public int this[int i]
    {
        get => _v[i];
        set => _v[i] = value;
    }
}

class Program
{
    static void Main()
    {
        var d = new Demo();
        d[0] = 100;
        Console.WriteLine(d[0]);
    }
}

Часто задаваемые вопросы

Урок «Индексаторы» бесплатный?

Да — полный текст урока «Индексаторы» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс C# Academy, подпишись на CoddyKit PRO. Курс C# Academy содержит 4 уроков всего.

Чему я научусь в уроке «Индексаторы»?

Обращайтесь к объектам с помощью синтаксиса, похожего на работу с массивами. Ты практикуешь C# Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать C# Academy?

Предыдущий опыт не требуется. C# Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.

Сколько времени занимает урок «Индексаторы»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке C# Academy?

Да. Каждый урок C# Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Автоматически реализуемые свойства
  2. Полные свойства с резервными полями
  3. Члены с телом-выражением
  4. Индексаторы
← Назад к C# Academy