Индексаторы. Одномерные и многомерные индексаторы. Индексаторы без базового массива. Перегрузка индексаторов
Содержание
- 1. Что называется индексатором? Каким образом индексаторы применяются в программах? Общая форма объявления индексатора
- 2. Пример объявления одномерного индексатора, который возвращает значение типа char
- 3. Пример объявления одномерного индексатора, возвращающего значение типа int
- 4. Пример объявления одномерного индексатора в котором реализован индекс типа char
- 5. Пример объявления двумерного индексатора
- 6. Пример объявления трехмерного индексатора
- 7. Какие особенности использования индексаторов без базового массива
- 8. Пример объявления класса, который содержит индексатор, но не содержит базового массива. Вычисление значения n-го числа Фибоначчи
- 9. Что называется перегрузкой индексаторов?
- 10. Пример объявления класса, в котором используются перегруженные индексаторы
- Связанные темы
Поиск на других ресурсах:
1. Что называется индексатором? Каким образом индексаторы применяются в программах? Общая форма объявления индексатора
Индексатор – это средство языка C#, позволяющее индексировать объект так как массив с помощью прямоугольных скобок [ ]. С помощью индексаторов можно реализовывать собственные специализированные массивы, на которые могут накладываться различные ограничения.
Чтобы использовать индексаторы в программах нужно объявить класс, содержащий индексатор. Класс может иметь внутренний массив, к элементам которого осуществляется доступ с помощью индексатора. После объявления класса с индексатором можно использовать объект этого класса как массив (с помощью прямоугольных скобок [ ]). Чтобы использовать индексатор, он должен быть объявлен как public.
Так как и массивы, индексаторы могут быть одномерные и многомерные.
Общая форма объявления индексатора в некотором классе:
type this[type_index index] { get { // код, который возвращает значение по индексу index // ... } set { // код, который устанавливает значение по индексу // ... } }
где
- type – тип элемента индексатора;
- index – индекс или позиция элемента в массиве по которому осуществляется доступ к элементу;
- type_index – тип индекса (позиции) индексатора. Как правило это тип int. Однако, допускается наличие других типов (например double, char);
- this – ссылка на данный класс, в котором реализуется индексатор;
- get, set – аксессоры соответственно для чтения (get) значения элемента и записи (set) значения в элемент.
⇑
2. Пример объявления одномерного индексатора, который возвращает значение типа char
Одномерный индексатор соответствует одномерному массиву. В примере объявляется класс CharArray, содержащий индексатор.
// класс, который содержит индексатор class CharArray { char[] A; // конструктор класса public CharArray(int size) { if (size > 26) size = 26; A = new char[size]; for (int i = 0; i < size; i++) A[i] = (char)((int)'A' + i); } // объявление индексатора public char this[int index] { get // чтение из позиции index { if ((index >= 0) && (index < A.Length)) return A[index]; else return 'A'; } set // запись в позицию index { if ((index>=0) && (index<A.Length)) A[index] = value; } } }
В вышеприведенном коде объявляется индексатор, возвращающий значение элементов типа char. Значения индексов имеют тип int.
В индексаторе реализуются два аксесора: get, set. В теле реализации аксессоров осуществляется проверка на выход индекса за пределы допустимого диапазона [0 .. Size-1].
Демонстрация использования класса в другом программном коде
... // использование класса CharArray CharArray cA = new CharArray(15); // массив из 15 символов char c; c = cA[0]; // c = 'A' c = cA[3]; // c = 'D' c = cA[10]; // c = 'K' c = cA[14]; // c = 'O' c = cA[15]; // c = 'A' - попытка доступа за допустимые пределы c = cA[30]; // c = 'A' - попытка доступа за допустимые пределы cA[3] = 'Z'; c = cA[3]; // c = 'Z' cA[30] = 'X'; // допускается, но блокируется в в аксессоре set { ... } c = cA[30]; // c = 'A' ...
⇑
3. Пример объявления одномерного индексатора, возвращающего значение типа int
В примере реализуется класс, который содержит одномерный индексатор, который возвращает значение типа int. Тип индексов в индексаторе также int.
// класс, содержащий индексатор class IntArray { int[] Array; // массив public IntArray(int size) { // выделить память для массива Array = new int[size]; // обнулить массив for (int i = 0; i < size; i++) Array[i] = 0; } // индексатор public int this[int index] { // аксессоры get { return Array[index]; } set { Array[index] = value; } } }
Использование класса IntArray в другом программном коде
// использование класса IntArray IntArray iA = new IntArray(100); int i; int d; // заполнение значениями массива через индексатор for (i = 0; i < 100; i++) iA[i] = i * i + 1; d = iA[3]; // d = 10 d = iA[25]; // d = 626 iA[25] = 15; d = iA[25]; // d = 15
⇑
4. Пример объявления одномерного индексатора в котором реализован индекс типа char
Тип индекса в индексаторе не обязательно должен быть целочисленным. Можно объявлять и другой тип индекса, например double, char. Но в этом случае при использовании внутреннего массива нужно привести тип индекса из другого типа (double, char, …) к типу int.
Следующий пример демонстрирует применение индексатора в классе, в котором значение индекса есть числом типа char. Данный пример реализует подсчет количества символов латинского алфавита ‘A’ … ‘Z’ в заданной строке.
// класс, в котором индекс в индексаторе есть типа char class CharIndex { int[] Array; int Size; public CharIndex() { Size = 26; Array = new int[Size]; for (int i = 0; i < Size; i++) Array[i] = 0; } // индексатор public int this[char symbol] { get { if ((symbol>='A') && (symbol<='Z')) return Array[(int)((int)symbol - (int)'A')]; return 0; } set { if ((symbol>='A') && (symbol<='Z')) Array[(int)symbol-(int)'A'] = value; } } }
Как видно из вышеприведенного кода, в аксессорах get и set, индекс массива Array приводится к типу int. Однако, из программного кода, к объекту класса CharIndex можно доступиться по индексу типа char.
Использование класса в другом программном коде
// использование класса CharIndex CharIndex cI = new CharIndex(); string s = "USING AN INDEXERS IN PROGRAMS"; int d; int i; char c; // подсчет количества символов 'A'..'Z' for (i = 0; i < s.Length; i++) cI[s[i]]++; d = cI['U']; // d = 1 d = cI['A']; // d = 2 d = cI['N']; // d = 4 d = cI['I']; // d = 3
⇑
5. Пример объявления двумерного индексатора
В примере объявляется двумерный индексатор, который реализует двумерный массив чисел типа double.
// класс, который реализует двумерный индексатор class TwoDimIndexes { double[,] A; // внутренний массив элементов int m, n; // размерность массива // конструктор public TwoDimIndexes(int _m, int _n) { m = _m; n = _n; A = new double[m, n]; for (int i = 0; i < m; i++) for (int j = 0; j < n; j++) A[i, j] = 0; } // двумерный индексатор public double this[int i, int j] { get { return A[i, j]; } set { A[i, j] = value; } } }
Использование класса TwoDimIndexes в некотором программном коде
// использование класса TwoDimIndexes TwoDimIndexes dI = new TwoDimIndexes(3, 5); double x; // формирование массива с помощью индексатора for (int i = 0; i < 3; i++) for (int j = 0; j < 5; j++) dI[i, j] = i * 2 + j; x = dI[1, 3]; // x = 1*2 + 3 = 5 x = dI[2, 0]; // x = 4
⇑
6. Пример объявления трехмерного индексатора
Объявляется класс, который содержит трехмерный индексатор
// класс, в котором объявляется трехмерный индексатор class ThreeDimIndexes { double[, ,] M; // трехмерный массив int x, y, z; // размерность массива // конструктор public ThreeDimIndexes(int _x, int _y, int _z) { x = _x; y = _y; z = _z; // Выделить память для массива M M = new double[3, 4, 5]; } // трехмерный индексатор public double this[int i, int j, int k] { get { bool fi, fj, fk; // проверка на допустимые границы индексов массива fi = (i >= 0) && (i < x); fj = (j >= 0) && (j < y); fk = (k >= 0) && (k < z); if (fi && fj && fk) return M[i, j, k]; else return 0.0; } set { bool fi, fj, fk; // проверка на допустимые границы индексов массива fi = (i >= 0) && (i < x); fj = (j >= 0) && (j < y); fk = (k >= 0) && (k < z); if (fi && fj && fk) M[i, j, k] = value; else M[i, j, k] = 0.0; } } }
Использование класса в другом программном коде
// использование класса ThreeDimIndexes ThreeDimIndexes dI = new ThreeDimIndexes(3, 4, 5); double x; // формирование значений элементов массива с помощью индексатора int i, j, k; for (i = 0; i < 3; i++) for (j = 0; j < 4; j++) for (k = 0; k < 5; k++) dI[i, j, k] = i * 2.5 + j * 2 + k; x = dI[0, 1, 3]; // x = 0*2.5 + 1*2 + 3 = 5.0 x = dI[1, 3, 2]; // x = 1*2.5 + 3*2 + 2 = 10.5
⇑
7. Какие особенности использования индексаторов без базового массива
В классе не обязательно объявлять внутреннюю переменную-массив для того, чтобы использовать индексатор. Конечно, данные можно сохранять и во внутренней переменной (массиве). Однако, бывают случаи, когда значение элементов массива формируются программно, то есть поддаются некоторой закономерности или формуле. В этих случаях не обязательно объявлять внутренний массив, для сохранения которого нужна дополнительная память.
⇑
8. Пример объявления класса, который содержит индексатор, но не содержит базового массива. Вычисление значения n-го числа Фибоначчи
В классе CFibonacci объявляется индексатор, который формирует число Фибоначчи на основе его позиции в ряде. Для определения числа, в классе реализован скрытый (private) дополнительный метод GetNumber(). Класс не содержит конструктора. Индексатор в классе содержит только один аксессор get.
Реализация класса имеет следующий вид
// класс, который содержит индексатор без использования внутреннего массива class CFibonacci { // внутренний метод // вычисляет значение числа Фибоначчи по его позиции index private int GetNumber(int index) { if (index < 0) return -1; int t = 0; if (index == 1) t = 1; if (index == 2) t = 1; if (index > 2) { int t1, t2; int i; t1 = t2 = 1; i = 2; while (i < index) // цикл вычисления числа Фибоначчи { t = t1 + t2; t1 = t2; t2 = t; i++; } } return t; } // индексатор public int this[int index] { get { return GetNumber(index); } } }
Использование класса CFibonacci в другом программном коде
// использование индексатора без внутреннего базового массива CFibonacci cF = new CFibonacci(); int d; // прочитать число Фибоначчи d = cF[5]; // d = 5 d = cF[7]; // d = 13 d = cF[10]; // d = 55
⇑
9. Что называется перегрузкой индексаторов?
Перегрузка индексатора – это реализация в классе нескольких индексаторов, которые имеют разные типы индекса (например int, char, double).
В общем виде реализация такого класса выглядит следующим чином:
class ClassName { ... public return_type this[type1 index] { // ... } public return_type this[type2 index] { // ... } ... public return_type this[typeN index] { // ... } ... }
где
- ClassName – имя класса, в котором объявляется перегруженный индексатор;
- return_type – тип элемента индексатора. Этот тип есть общим для всех перегруженных индексаторов;
- type1, type2, …, typeN – типы индексов с именем index.
⇑
10. Пример объявления класса, в котором используются перегруженные индексаторы
В классе CDoubleArray демонстрируется использование перегруженного индексатора
// класс, который содержит перегруженный индексатор class CDoubleArray { double[] A; int length; public CDoubleArray(int _length) { length = _length; A = new double[length]; for (int i = 0; i < length; i++) // занести произвольные значения в массив A[i] = i * 2; } // перегруженный индексатор public double this[int index] { get { return A[index]; } set { A[index] = value; } } public double this[double index] { get { return A[(int)(index+0.5)]; } set { A[(int)(index+0.5)] = value; } } }
Использование класса CDoubleArray в другом программном коде
// использование перегруженного индексатора CDoubleArray dA = new CDoubleArray(10); double d; d = dA[3]; // d = 6 d = dA[3.3]; // d = 6 d = dA[3.5]; // d = 8 dA[4.7] = 1100; d = dA[5]; // d = 1100
⇑
Связанные темы
- Одномерные массивы. Примеры решения задач на одномерные массивы. Массивы структур. Массивы классов
- Многомерные массивы. Ступенчатые массивы
- Свойства. Аксессоры get, set. Примеры классов содержащих свойства