Индексаторы в C#

Индексаторы в C#

В этой статье я расскажу о том, что такое индексаторы, зачем они нужны, как и когда ими пользоваться в своих программах, написанных на языке C#. И так, индексаторы нужны в тех случаях, когда мы пишем класс, ведущий себя как некая коллекция, например, в нем есть поле-массив, например, такой класс:

//Класс-коллекция целых чисел
class SomeCollection
{
    //Конструктор, создает объект коллекцию, с указанием её размера
    public SomeCollection(int aSize)
    {
        collection = new int[aSize];
    }

    //Свойство, возвращающее размер коллекции (только для чтения)
    public int Size { get { return collection.Length; } }

    //Поле-массив, для хранения элементов коллекции
private int[] collection;
}

Как видно из примера, в классе есть поле-массив, есть конструктор, который задает размер массива, и свойство, возвращающее размер массива «внешнему миру». Но нужно же еще как-то организовать доступ к элементам массива, чтобы пользователи нашего класса могли изменять и получать содержимое внутреннего массива. Тут конечно можно написать пару методов, один будет возвращать значение элемента с указанным, в качестве аргумента метода, индексом, а второй метод, будет устанавливать значение указанного (тем же способом) элемента. И выглядело бы это примерно так:

//Клсаа-коллекция целых чисел
class SomeCollection
{
    //Конструктор, создает объект коллекцию, с указанием её размера
    public SomeCollection(int aSize)
    {
        collection = new int[aSize];
    }

    //Метод, возвращающий значение элемента, по указанному индексу
    public int GetElem(int anIndex)
    {
        return collection[anIndex];
    }

    //Метод, устанавливающий значение элемента, по указанному индексу
    public void SetElem(int aValue, int anIndex)
    {
        collection[anIndex] = aValue;
    }
 
    //Свойство, возвращающее размер коллекции (только для чтения)
    public int Size { get { return collection.Length; } }

    //Поле-массив, для хранения элементов коллекции
    private int[] collection;
}

А использование объектов данного класса могло бы выглядеть так:

//Создать коллекцию
SomeCollection tmpColl = new SomeCollection(20);

//Перебрать все элементы коллекции
for (int i = 0; i < tmpColl.Size; i++)
{
    //Установить значение элементу с индексом i
    tmpColl.SetElem(i + 1, i);
}

//Перебрать все элементы коллекции
for (int i = 0; i < tmpColl.Size; i++)
{
    //Вывести в консоль элемент коллекции с индексом i
    Console.Write(tmpColl.GetElem(i) + " ");
}

//Перевод строки
Console.WriteLine("");

Можете создать новый проект, и проверить это дело на практике… Но можно решить задачу организации доступа к элементам встроенного в объект массива гораздо элегантнее! Вот тут мы и будем использовать индексаторы. Давайте добавим в наш класс индексатор, а выглядеть он будет так:

/*
 * Индексатор (похож на свойство, но со специфическим именем и 
 * дополнительным параметром, указанным в квадратных скобках)
 */ 
 public int this[int anIndex]
 {
 //Метод доступа get
 get { return collection[anIndex]; }
 //Метод доступа set
 set { collection[anIndex] = value; }
 }

Как видите, индексатор очень похож на свойство, но у него должно быть специфическое имя «this» и дополнительный параметр в квадратных скобках (которого нет у обычного свойства).

Вообще this — это ключевое слово языка C# и оно имеет особое значение (используется не только в индексаторах), о котором я как-нибудь расскажу в одной из статей.

Этот дополнительный параметр используется как индекс, для обращения к внутреннему массиву. Использование объектов класса, в который мы добавили индексатор выглядит как использование массивов:

//Создать коллекцию
SomeCollection tmpColl = new SomeCollection(20);

//Перебрать все элементы коллекции
for (int i = 0; i < tmpColl.Size; i++)
{
    //Установить значение элементу с индексом i
    tmpColl[i] = i + 1;
}

//Перебрать все элементы коллекции
for (int i = 0; i < tmpColl.Size; i++)
{
    //Вывести в консоль элемент коллекции с индексом i
    Console.Write(tmpColl[i] + " ");
}

//Перевод строки
Console.WriteLine("");

Согласитесь, этот вариант короче и удобнее! Ну пока хватит информации об индексаторах, как-нибудь я подробнее рассажу о них…

Добавить комментарий