Индексаторы. Определение одномерного индексатора. Класс «Безопасный массив». Виртуальный массив.

Определение одномерного индексатора

В некоторых ситуациях бывает удобно индексировать (нумеровать) содержимое объекта так, словно он представляет собой массив. Особенно если поля класса представляют собой массив, стек или какие-то перечисления. Такая задача решается разработкой индексатора.

Индексация массивов реализуется с помощью оператора массива, который обозначается [ ]. С его помощью, можно получить доступ к отдельному элементу массива (mas[2], ... , mas[i]).

C# позволяет строить пользовательские классы и структуры, которые могут индексироваться как массивы. Тогда к i-ому элементу значения объекта можно подступиться как Ob[i].

Свойства и индексаторы расширяют возможности класса. Свойства предлагают эффективный способ управления доступом к данным объекта. Индексаторы обеспечивают механизм, посредством которого к объектам можно получать доступ по индексам на основе синтаксиса массивов. То есть индексируемый объект выглядит как массив, но для выполнения индексации в нём определяют специальные функции доступа.

Итак, индексатор позволяет обеспечить индексируемый доступ к объекту. Его главное назначение – создавать специализированные (ранжированные) массивы, на которые налагается одно или несколько ограничений. Индексаторы позволяют использовать синтаксис работы с массивами для доступа к классу, который содержит: массив, какие-то перечисления (enum), а так же наборы (коллекции или семейства). При использовании индексаторов пользовательские коллекции работают с базовыми библиотеками .NET.

Индексатор в C# представляет собой несколько «искажённое» свойство. Индексаторы могут характеризоваться одной или несколькими размерностями.

Создание одномерных индексаторов. Формат записи одномерного индексатора:

public Тип_элемента_объекта this [int индекс] // this - этот

{

Get //Аксессор считывания данных

{

//Возврат значения, заданного индексом.

}

Set //Аксессор установки данных.

{

//Установка значения элементу, заданному индексом

}

}

Объявление индексатора похоже на объявление свойства, но в нём используются указатель this и индекс. Оба аксессора в качестве параметра принимают индекс. Например:

Ob[5] = 13.87; // [5] - это и есть индексатор. Здесь работал set- аксессор.

double z = Ob[2] + 100; // Здесь работал get-аксессор.

Класс «Безопасный массив»

Задание: В проекте «Первые_учебные_классы» создать класс Bezopasn_mas (Безопасный массив) с использование одномерного индексатора. Под безопасностью понимается проверка выхода индекса за пределы границ массива.

class Bezopasn_mas

{

double [] mas; //

Int dlina; // Закрытые поля класса

bool errflag; //

// Конструктор:

public Bezopasn_mas(int size)

{

dlina = size;

mas = new double[size]; // Позднее связывание ссылочной переменной с памятью.

}

// Свойства:

Public int Razmer

{

get { return dlina; }

}

Public bool Oshibka

{

get { return errflag; }

}

}

Для разработки индексатора создадим закрытый вспомогательный метод OK(int index), который возвращает true, если индекс находится в пределах границ массива, а иначе возвращает false.

Private bool OK(int index)

{

if (index >= 0 && index < Razmer)

return true;

Else

return false;

}

// Индексатор:

public double this [int index]

{

Get

{

If (OK(index))

{

errflag = false; // Ошибки нет!

return mas[index];

}

Else

{

errflag = true; //Ошибка индекса!

Return 0; // С целью безопасности программа должна работать далее. Мы возвращаем ноль.

}

}

Set

{

If (OK(index))

{

errflag = false; //Ошибки нет!

mas[index] = value;

}

Else

errflag = true;

}

}

//В Main():

Bezopasn_mas Ob1 = new Bezopasn_mas(5);

int i=0; double x=0;

Console.WriteLine("Мягкое приземление! Работа с массивом без уведомлений об ошибках");

Заполняя массив, нарушим его границы:

for (i = 0; i < Ob1.Razmer * 2; i++)

{

Console.WriteLine("Введите " + i + " элемент массива!");

Ob1[i] = Double.Parse(Console.ReadLine());

}

Console.WriteLine("Содержимое массива");

for (i = 0; i < Ob1.Razmer * 2; i++)

{

x = Ob1[i];

Console.Write(x+ " ");

}

Console.WriteLine();

//Выполнить!

Console.WriteLine("Работа с объектом-массивом с выдачей сообщений об ошибке!");

for (i = 0; i < Ob1.Razmer * 2; i++)

{

Console.WriteLine("Введите " + i + " элемент массива!");

Ob1[i] = Double.Parse(Console.ReadLine());

if (Ob1.Oshibka)

Console.WriteLine("Элемент с номером " + i + " вне границ!");

}

Console.WriteLine("Содержимое массива");

for (i = 0; i < Ob1.Razmer * 2; i++)

{

x = Ob1[i];

if (Ob1.Oshibka)

Console.WriteLine("Элемент с номером " + i + " вне границ!");

Console.Write(x+ " ");

}

Console.WriteLine();

Виртуальный массив

Индексатор может не использовать базовый массив, объявленный в классе. Вполне достаточно, чтобы индексатор обеспечивал функционирование, которое для пользователя выглядело бы так, как будто идёт работа с массивом (виртуальный массив).
Задание: В проект «Первые_учебные_классы» добавить новый класс: Stepeni_2. В этом классе создать индексатор, который действует подобно массиву, предназначенному только для чтения. Такой виртуальный массив будет содержать степени числа 2 от 0 до 15. В действительности же никакого массива НЕТ. Роль индекса будет играть показатель степени.

Существует много алгоритмов, в которых вычисляется какой-то i-й элемент: числа Фибоначчи, целая степень числа, очередной член ряда Тейлора и другие.

//Разработка класса Stepeni_2:

//Вспомогательный закрытый метод Stepen(int pokaz):

Наши рекомендации