Урок 13. Индексаторы C#
Тринадцатый урок учебника по объектно-ориентированному программированию на языке C# описывает использование индексаторов. Класс, имеющий индексатор, можно использовать аналогично массиву. Объекты класса могут использовать нотацию в стиле массива для представления нескольких значений.
Что такое индексатор?
Большинство программистов на C# сначала используют индексатор при работе с массивом. Массив используется для хранения ряда похожих, связанных переменных под одним и тем же именем, причем каждая переменная доступна с помощью индексного номера, заключенного в квадратные скобки. Например:
thirdItem = items[3];Часто бывает полезно включить обозначение квадратных скобок для новых классов. Это может быть связано с тем, что класс используется для хранения связанной информации аналогично массиву, или просто потому, что номер индекса может быть полезен при вычислении или поиске. Добавление индексатора в класс обеспечивает эту функциональность.
Создание индексатора
Самый простой вариант индексатора - одномерный тип. Одномерный индексатор принимает одно значение между квадратными скобками при использовании. Стандартный синтаксис, используемый для объявления индексатора, аналогичен синтаксису, используемому для определения методов доступа get и set свойства. Однако вместо определения имени свойства методы доступа объявляются для этого[] следующим образом:
public data-type this[index-type index-name] { get {} set {} }В определении синтаксиса тип данных определяет тип информации, которая будет возвращена при запросе индексатора, и тип, который будет необходим при установке значения. Тип индекса указывает тип данных самого индексатора. Это позволяет объявлять индексаторы, которые не основаны на целочисленных значениях, что позволяет использовать аналогичную функциональность, например, для хэш-таблицы. Имя индекса - это переменная, содержащая значение индекса, которое может быть использовано при обработке методов доступа get и set.
Метод доступа get необходим для индексатора и должен возвращать значение типа data-type. Метод доступа set определен для индексаторов с возможностью записи и опущен, если требуется вариант только для чтения.
Создание нового класса типа массива
Чтобы продемонстрировать использование индексатора, в этой статье мы создадим новый класс, который ведет себя как простой массив строковых переменных. В отличие от стандартного массива, который допускает только нулевое индексирование, новый класс будет предоставлять массив на основе целых чисел, для которого программист может указать верхнюю и нижнюю границы с помощью конструктора во время создания экземпляра.
Для начала создайте новое консольное приложение с именем "IndexerDemo "и добавьте новый файл класса с именем "MyArray".
Добавление переменных класса
Новый массивоподобный класс требует трех приватных переменных. Две целочисленные величины будут содержать верхнюю и нижнюю границы. Массив строк также потребуется для хранения элементов, добавленных в класс MyArray. Это будет нулевой массив с той же длиной, что и созданный объект MyArray. Индексатор интерпретирует предоставленный номер индекса и сопоставляет его с этим базовым массивом для операций get и set.
Чтобы добавить переменные уровня класса, добавьте следующий код в блок кода класса MyArray:
int _lowerBound; int _upperBound; string[] _items;Добавление конструктора
Конструктор для нового класса будет принимать два целочисленных параметра, определяющих верхнюю и нижнюю границы. Эти значения будут сохранены в двух связанных переменных класса. Используя эти границы, можно вычислить длину базового массива и соответствующим образом инициализировать массив _items.
Чтобы создать конструктор, добавьте в класс следующий код:
public MyArray(int lowerBound, int upperBound) { _lowerBound = lowerBound; _upperBound = upperBound; _items = new string[1 + upperBound - lowerBound]; }Примечание: Для упрощения в этом примере проверки были опущены. В реальной программе вы бы хотели проверить, что верхняя граница больше, чем нижняя граница. Другие проверочные проверки в приведенном ниже коде также были удалены для большей ясности.
Добавление индексатора
Теперь, когда подготовительная работа завершена, мы можем добавить индексатор в класс. Для этого простого класса типа массива индексатор принимает один целочисленный параметр, содержащий индекс строки, которая считывается или записывается. Этот индекс необходимо настроить для корректного сопоставления с базовыми данными, прежде чем возвращать значение из массива или записывать новое значение в массив.
Код для добавления индексатора показан ниже. Обратите внимание, что, как и в случае с объявлениями свойств, метод доступа set использует переменную value для определения значения, присвоенного вызывающей функцией:
public string this[int index] { get { return _items[index - _lowerBound]; } set { _items[index - _lowerBound] = value; } }Новый класс может быть протестирован с помощью основного метода программы. Откройте класс Program и добавьте следующий код, чтобы создать новый экземпляр MyArray и заполнить его значениями.
static void Main(string[] args) { MyArray fruit = new MyArray(-2, 1); fruit[-2] = "Apple"; fruit[-1] = "Orange"; fruit[0] = "Banana"; fruit[1] = "Blackcurrant"; Console.WriteLine(fruit[-1]); // "Orange" Console.WriteLine(fruit[0]); // "Banana" }Создание многомерных индексаторов
Индексаторы не ограничиваются одним измерением. Включив в квадратные скобки объявления индексатора более одной индексной переменной, можно добавить несколько измерений. Например, для объявления двумерного индексатора используется следующий синтаксис:
public data-type this[index-type1 index-name1, index-type2 index-name2] { get {} set {} }Также возможна перегрузка индексаторов. Она происходит таким же образом, как перегрузка методов. Несколько объявлений для this[] могут быть включены каждый с различным набором параметров или сигнатурой. Мы можем продемонстрировать это, добавив второй индексатор в класс MyArray. На этот раз индексатор будет иметь два целых параметра. Первый определит, какой элемент из частного массива будет найден. Второй параметр определяет позицию внутри строки и возвращает символ в этой позиции. Для простоты следующий код создает перегруженный индексатор только для чтения.
public string this[int word, int position] { get { return _items[word - _lowerBound].Substring(position, 1); } }Чтобы протестировать второй индексатор, измените основной метод следующим образом:
static void Main(string[] args) { MyArray fruit = new MyArray(-2, 1); fruit[-2] = "Apple"; fruit[-1] = "Orange"; fruit[0] = "Banana"; fruit[1] = "Blackcurrant"; Console.WriteLine(fruit[-1, 0]); // "O" Console.WriteLine(fruit[0, 2]); // "n" }Создание индексатора без базового массива
Как уже упоминалось в начале этой статьи, нет никаких требований, чтобы индексатор был связан с базовым массивом или коллекцией. Иногда полезно использовать индексатор для ссылки на строку из таблицы базы данных, позицию в текстовом файле или XML-документе или просто для выполнения вычисления.
Следующий индексатор, добавленный в класс MyArray,вообще не использует поиск. Вместо этого значение с плавающей запятой (float), передаваемое индексатору, просто возведено в квадрат:
public float this[float toSquare] { get { return toSquare * toSquare; } }Это можно проверить с окончательным изменением основного метода:
static void Main(string[] args) { MyArray fruit = new MyArray(0, 0); Console.WriteLine(fruit[5F]); // 25 }
Автор этого материала - я - Пахолков Юрий. Я оказываю услуги по написанию программ на языках Java, C++, C# (а также консультирую по ним) и созданию сайтов. Работаю с сайтами на CMS OpenCart, WordPress, ModX и самописными. Кроме этого, работаю напрямую с JavaScript, PHP, CSS, HTML - то есть могу доработать ваш сайт или помочь с веб-программированием. Пишите сюда.
Отправляя сообщение я подтверждаю, что ознакомлен и согласен с политикой конфиденциальности данного сайта.