Индексаторы
Обращайтесь к объектам с помощью синтаксиса, похожего на работу с массивами.
«Индексаторы» — бесплатный урок 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 — локальная установка не требуется.
Все уроки этого курса
- Автоматически реализуемые свойства
- Полные свойства с резервными полями
- Члены с телом-выражением
- Индексаторы