При выполнении этой программы получается следующий результат. Как показывает приведенный выше результат, индексы типа double округляются до ближайшего целого значения

f S [ 1 ] : 1

fs [2] : 2 fs[1 -1 ] : 1 f s [ 1. 6 ] : 2

Как показывает приведенный выше результат, индексы типа double округляются до ближайшего целого значения. В частности, индекс 1.1 округляется до 1, а индекс 1.6 — до 2.

Представленный выше пример программы наглядно демонстрирует правомочность перегрузки индексаторов, но на практике она применяется нечасто. Как правило, индексаторы перегружаются для того, чтобы использовать объект определенного класса в качестве индекса, вычисляемого каким-то особым образом.

Индексаторы без базового массива

Следует особо подчеркнуть, что индексатор совсем не обязательно должен оперировать массивом. Его основное назначение — предоставить пользователю функциональные возможности, аналогичные массиву. В качестве примера в приведенной ниже программе демонстрируется индексатор, выполняющий роль массива только для чтения, содержащего степени числа 2 от 0 до 15. Обратите внимание на то, что в этой программе отсутствует конкретный массив. Вместо этого индексатор просто вычисляет подходящее значение для заданного индекса.

// Индексаторы совсем не обязательно должны оперировать отдельными массивами.

Using System;

class PwrOfTwo {

/* Доступ к логическому массиву, содержащему степени числа 2 от 0 до 15. */ public int this[int index] {

// Вычислить и возвратить степень числа 2. get {

if((index >= 0) && (index < 16)) return pwr(index);

Else return -1;

}

// Аксессор set отсутствует.

}

int pwr(int p) { int result = 1;

for(int i=0; i < p; i++) result *= 2;

Return result;

}

}

class UsePwrOfTwo { static void Main() {

PwrOfTwo pwr = new PwrOfTwo();

Console.Write("Первые 8 степеней числа 2: "); for(int i=0; i < 8; i++)

Console.Write(pwr[i] + " ");

Console.WriteLine();

Console.Write("А это некоторые ошибки: ");

Console.Write(pwr[-1] + " " + pwr[17]);

Вот к какому результату приводит выполнение этой программы.

Первые 8 степеней числа 2: 1 2 4 8 16 32 64 128 А это некоторые ошибки: -1 -1

Обратите вйимание на то, что в индексатор класса PwrOf Two включен только аксессор get, но в нем отсутствует аксессор set. Как пояснялось выше, такой индексатор служит только для чтения. Следовательно, объект класса PwrOf Two может указываться только в правой части оператора присваивания, но не в левой его части. Например, попытка ввести следующую строку кода в приведенную выше программу не приведет к желаемому результату.

pwr[0] =11; //не подлежит компиляции

Такой оператор присваивания станет причиной появления ошибки во время компиляции, поскольку для индексатора не определен аксессор set.

На применение индексаторов накладываются два существенных ограничения. Во-первых, значение, выдаваемое индексатором, нельзя передавать методу в качестве параметра ref или out, поскольку в индексаторе не определено место в памяти для его хранения. И во-вторых, индексатор должен быть членом своего класса и поэтому не может быть объявлен как static.

Многомерные индексаторы

Индексаторы можно создавать и для многомерных массивов. В качестве примера ниже приведен двумерный отказоустойчивый массив. Обратите особое внимание на объявление индексатора в этом примере.

// Двумерный отказоустойчивый массив.

Using System;

class FailSoftArray2D {

int[,] a; // ссылка на базовый двумерный массив int rows, cols; // размеры массива

public int Length; // открытая переменная длины массива public bool ErrFlag; // обозначает результат последней операции

// Построить массив заданных размеров, public FailSoftArray2D(int г, int с) { rows = г; cols = с;

а = new int[rows, cols];

Length = rows * cols;

}

// Это индексатор для класса FailSoftArray2D. public int this[int indexl, int index2] {

// Это аксессор get. get {

if(ok(indexl, index2)) {

ErrFlag = false;

return a[indexl, index2];

} else {

ErrFlag = true; return 0;

}

}

// Это аксессор set. set {

if(ok(indexl, index2)) {

a[indexl, index2] = value;

ErrFlag = false;

}

else ErrFlag = true;

}

}

// Возвратить логическое значение true, если // индексы находятся в установленных пределах, private bool ok(int indexl, int index2) {

•if (indexl >= 0 & indexl < rows & index2 >= 0 & index2 < cols) return true;

Return false;

}

}

// Продемонстрировать применение двумерного индексатора, class TwoDIndexerDemo { static void Main() {

FailSoftArray2D fs = new FailSoftArray2D(3, 5); int x;

// Выявить скрытые сбои.

Console.WriteLine("Скрытый сбой."); for (int i=0; i < 6; i++) fs[i, i]=i*10;

for(int i=0; i < 6; i++) {

x = f s [ i, i ] ;

if(x != -1) Console.Write (x + " ");

}

Console.WriteLine ();

// А теперь показать сбои.

Console.WriteLine("\пСбой с уведомлением об ошибках."); for(int i=0; i < 6; i++) {

fs[i,i] = i *10; if(fs.ErrFlag)

Console.WriteLine("fs[" + i + ", " + i + "] вне границ

}

for(int i=0; i < 6; i++) {

x = f s [ i, i ] ;

if(!fs.ErrFlag) Console.Write(x + " ");

Else

Console.WriteLine("fs[" + i + ", " + i + "] вне границ");

}

}

}

Вот к какому результату приводит выполнение этого кода:

Скрытый сбой.

0 10 20 0 0 0

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