Індексатори. Одновимірні та багатовимірні індексатори. Індексатори без базового масиву. Перевантаження індексаторів
Зміст
- 1. Що називається індексатором? Як індексатори застосовуються у програмах? Загальна форма оголошення індексатора
- 2. Приклад оголошення одновимірного індексатора, що повертає значення типу char
- 3. Приклад оголошення одновимірного індексатора, що повертає значення типу int
- 4. Приклад оголошення одновимірного індексатора в якому індекс є типу char
- 5. Приклад оголошення двовимірного індексатора
- 6. Приклад оголошення тривимірного індексатора
- 7. Які особливості використання індексаторів без базового масиву
- 8. Приклад оголошення класу, що містить індексатор, але не містить базового масиву
- 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. Приклад оголошення класу, що містить індексатор, але не містить базового масиву
У класі 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. Приклади класів, що містять властивості