Одномерные индексаторы и Многомерные индексаторы в C#
Для обращения к элементам массива обычно применяются квадратные скобки, внутри которых записывают индексы. В языке С# имеется возможность проектировать специальные классы и структуры, которые могут быть индексированы подобно стандартному массиву, посредством определения индексатора. Это конкретное языковое средство наиболее полезно при создании специальных типов коллекций (обобщенных и необобщенных). Индексаторы могут быть одно- или многомерными.
Одномерные индексаторы
Ниже приведена общая форма одномерного индексатора:
тип_элемента this[int индекс]
{
// Аксессор для получения данных,
get
{
// Возврат значения, которое определяет индекс.
}
// Аксессор для установки данных,
set
{
// Установка значения, которое определяет индекс, через value.
}
}
где тип_элемента указывает на тип элемента, с которым «работает» индексатор. Параметр «индекс» указывает на индекс элемента, к которому осуществляется доступ. Этот параметр должен быть целочисленного типа данных, например, типа int.
В теле индексатора определены два аксессора (т.е. средства доступа к данным): get и set. Аксессор подобен методу, за исключением того, что он не имеет типа возвращаемого значения и параметров (эти типы заданы в заголовке индексатора). Аксессоры вызываются автоматически в основной программе при обращении к массиву экземпляров класса, в котором объявлен индексатор, и них передается индекс, указанный при вызове. Если индексатор экземпляра класса указан слева от оператора присваивания, то вызывается аксессор set и массиву в экземпляре класса, на который указывает индекс, с помощью параметра value, присваивается значение, записанное справа от знака равенства. В противном случае вызывается аксессор get и возвращается значение, соответствующее элементу массива с заданным индексом. Таким образом индексатор является полной аналогией свойству.
Индексатор объявлен в некотором классе. Если этот класс содержит несколько массивов, то с помощью индексатора можно обращаться к любому из них, поскольку имя массива записывается слева от квадратных скобок.
Ниже приведен пример. Для сокращения примера массив в объекте класса выбран размерности 4 и заполняется из вспомогательного массива. Для наглядности тип значения для индекса и для индексатора выбраны разными:
class Ind_Test
{
double[ ] vec; // массив, хранящийся в классе Ind_Test
public Ind_Test(int Size) // Конструктор
{
vec = new double[Size]; // Объявления размерности массива
}
// Индексатор
public double this[int i] // Объявление типа элементов и типа индекса
{
set // Аксессор set
{
vec[i] = value; // Присвоение значения элементу массива
}
get // Аксессор get
{
return vec[i]; // Получение значения элемента массива
}
}
}
class Program
{
static void Main()
{
Ind_Test ar = new Ind_Test(4); // Объявление объекта класса Ind_Test
double [ ] n = new double [ ] { 2.5, 3.4, 4.3, 5.2}; // Вспомогательный массив
// Значение для каждого элемента массива vec объекта ar класса Ind_Test
for (int i = 0; i < n.Length; i++)
{
// Аксессор set присваивает значение для элемента массива vec
ar[i] = n[i];
Console.Write( "{0} ", ar[i]); // Просмотреть заполнение массива
}
Console.WriteLine("
"); //
for (int i = 0; i < n.Length; i++)
// Аксессор get получает значение vec из массива ar, затем умножение на 2
{
Console.Write( "{0:F} ", 2 * ar[i]);
}
Console.ReadKey(); //
}
}
Вывод программы имеет вид:
В классе Ind_Test определен индексатор, позволяющий вызывающей подпрограмме обращаться к экземплярам массива с помощью индексов.
Следует отметить, что индексатор может быть и не связан с массивом. Если есть некоторая функция, вычисление которой зависит от номера, (например, степень целого числа, число Фиббоначи и т. д.), то для получения значений такой функции может применяться индексатор.
Примечание: Значение, выдаваемое индексатором, не может передаваться в качестве ссылочного параметра при вызове подпрограммы (параметр не может иметь модификатор ref или out). Это связано с тем, что индексатор обращается к члену своего класса, поэтому сам не может быть ссылкой.
Ниже приведен пример программы, которая вычисляет число Фиббоначи по введенному номеру.
// Индексатор, вычисляющий n-ое число Фиббоначи:
class FibbNumber
{
public int this[int i] // Индексатор для чтения
{
get
{ // i – номер числа
if (i <=0) throw new Exception("Номера начинаются с 1");
else if (i==1 || i==2) return 1; // Первые 2 числа: 1 и 1
else
{
int prev = 1, curr = 1, next;
for (int k=3; k<=i; ++k) // Цикл до введенного номера
{
next = prev + curr; // Очередное число
prev = curr; // Перестановка
curr = next;
}
return curr;
}
}
}
}
class Program
{
static void Main()
{
Console.Write("n=");
Fibbonachy fib = new Fibbonachy();
try// Исключительная ситуация: ввод 0 или меньше
{
int n=int.Parse(Console.ReadLine());
Console.WriteLine("fib[{0}] = {1}", n, fib [n]);
}
catch (Exception e) // Исключительная ситуация пользователя
{
Console.WriteLine(e.Message); // Ошибка ввода
}
Console.ReadKey();
}
}
Последовательность имеет вид:
№ 1 2 3 4 5 6 7 8 9 10
Число 1 1 2 3 5 8 13 21 34 55
Вывод программы для n = 8.
Многомерные индексаторы
Можно создать индексатор, обеспечивающий обращение к элементам многомерных массивов. Ниже приведен пример индексатора для обращения к элементам матрицы:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class MyArr
{
int[,] arr;
// Размерность двухмерного массива
public int rows, cols;
public int Length; // Для получения объявленной размерности
public MyArr(int rows, int cols) // Конструктор
{
this.rows = rows;
this.cols = cols;
arr = new int[this.rows, this.cols];
Length = rows * cols;
}
// Индексатор
public int this[int index1, int index2]
{
get
{
return arr[index1, index2];
}
set
{
arr[index1, index2] = value;
}
}
}
class Program
{
static void Main(string[] args)
{
Random ran = new Random();
Console.WriteLine("Arr1:
");
MyArr arr1 = new MyArr(4,5);
for (int i = 0; i < arr1.rows - 1; i++)
{
for (int j = 0; j < arr1.cols - 1; j++)
{
arr1[i, j] = ran.Next(1,20);
Console.Write(arr1[i, j] + " ");
}
Console.WriteLine();
}
Console.ReadKey();
}
}
}
Вывод программы имеет вид:
Одномерные индексаторы и Многомерные индексаторы в C#
Лекции по предмету «Программирование»