Шаг 128.
Язык программирования C#. Начала
Свойства и индексаторы. Использование индексаторов

    На этом шаге мы рассмотрим примеры использования индексов.

    Теперь мы рассмотрим несколько примеров, в которых различными способами описываются индексаторы. Во всех примерах речь будет идти об индексаторах с одним индексом. Начнем с программы, которая наглядно иллюстрирует, что совсем необязательно, чтобы за индексатором "прятался" массив.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace pr128_1
{
    // Класс с индексатором:
    class MyClass {
        // Закрытое целочисленное поле: 
        private int code;
        // Конструктор с символьным аргументом: 
        public MyClass(char s) {
            // Присваивание значения полю: 
            code = s;
        }
        // Символьный индексатор с целочисленным индексом: 
        public char this[int k]{
            // Метод вызывается при считывании значения выражения
            //с проиндексированным объектом:
            get {
                // Значение свойства: 
                return (char)(code + k);
            }
            // Метод вызывается при присваивании значения 
            // выражению с проиндексированным объектом: 
            set {
                // Присваивание значения полю: 
                code = value - k;
            }
        }
    }

    // Класс с главным методом:
    class Program
    {
        // Главный метод: 
        static void Main()
        {
            // Создание объекта:
            MyClass obj = new MyClass('A');
            // Индексирование объекта для считывания значения: 
            for(int k = 0; k < 10; k++){
                Console.Write(obj[k] + " ");
            }
            Console.WriteLine();
            // Присваивание значения выражению с 
            // индексированным объектом: 
            obj[5] = 'Q';
            // Индексирования объекта для считывания значения: 
            for(int k=0; k < 10; k++){
                Console.Write(obj[k] + " ");
            }
            Console.WriteLine();
            // Использование отрицательного индекса 
            // при индексировании объекта: 
            for(int k = 0; k < 10; k++){
                Console.Write(obj[-k] + " ");
            }
            Console.WriteLine();
            // Задержка:
            Console.ReadLine();
        }
    }
}
Архив проекта можно взять здесь.

    Результат выполнения программы такой.


Рис.1. Результат выполнения программы

    Здесь в классе MyClass есть закрытое целочисленное поле code, значение которому присваивается при создании объекта. Причем аргументом конструктору передается символьное значение. Поэтому в поле code записывается код символа, переданного аргументом конструктору.

    Индексатор описан как такой, что относится к типу char (тип присваиваемого и возвращаемого значения), а индекс (обозначен как k) имеет тип int. В get-аксессоре индикатора выполняется команда

  return (char)(code + k);     , 
в соответствии с которой значением индексатора возвращается символ, код которого получается прибавлением к значению поля code значения индекса, указанного в квадратных скобках после имени объекта.

    В set-аксессоре выполняется команда

  code = value - k;    , 
которой значением полю code присваивается разность значения, указанного в операции присваивания, и индекса, указанного в выражении, которому присваивается значение. Причем подчеркнем, что параметр value в данном случае является символьным. Поэтому получается, что в поле code записывается код символа, который в кодовой таблице находится на k позиций перед тем символом, который указан в команде присваивания.

    В главном методе командой

  MyClass obj = new MyClass('A');
создается объект obj. Аргументом конструктору передан символ 'А'. Поэтому значением выражения obj[k] при заданном значении индекса k является символ, код которого на k больше, чем код символа 'А'. При выполнении цикла, в котором индексная переменная k пробегает значения от 0 до 9 включительно, отображается значение выражения obj[k], в результате чего появляется строка из десяти символов, начиная с символа 'А' и заканчивая символом 'J'.

    При выполнении команды

  obj[5] = 'Q';
в поле code объекта obj записывается код символа, находящегося в кодовой таблице за 5 позиций по отношению к символу 'Q'. Это символ 'L', и его код записывается в поле code. Поэтому при выполнении цикла, в котором индексная переменная k принимает значения от 0 до 9 и за каждую итерацию цикла отображается значение выражения obj[k], мы получаем последовательность из десяти символов, начиная с символа 'L' и заканчивая символом 'U'.

    Наконец, пикантность ситуации в том, что формально нам никто не запрещает использовать при индексации объекта отрицательный индекс. Главное, чтобы код аксессоров имел при этом смысл. Если мы выполним еще один цикл, но отображать будем значение выражения obj[-k], то получим последовательность символов, но в обратном порядке: от символа 'L' до символа 'С' включительно.

    На следующем шаге мы продолжим изучение этого вопроса.




Предыдущий шаг Содержание Следующий шаг