Учебно-методический комплекс общее количество часов 58 ч. Лекции 28 ч
Download 2.46 Mb.
|
Язык программирования C#
8.5. Индексаторы
Индексаторами называются свойства с параметрами. Индексаторы позволяют обращаться к объектам с использованием квадратных скобок подобно тому, как происходит обращение к массивам. Объявление индексаторов схоже с объявлением свойств, они также могут быть доступны только для чтения, только для записи или для чтения и записи одновременно. В отличии от свойств у индексаторов нет собственного имени (оно и ненужно), а для их объявления используется ключевое слово this. Общий формат для объявления индексаторов доступных для чтения и записи имеет следующий вид: спецификатор доступа тип0 this[тип1 пар1, тип2 пар2,…, типN парN] { спецификатор доступа set { } спецификатор доступа get { return значение; } } Если индексатор доступен только для чтения, блок set следует опустить. спецификатор доступа тип0 this[тип1 пар1, тип2 пар2,…, типN парN] { спецификатор доступа get { return значение; } } Если индексатор доступен только для записи, то следует опустить блок get. спецификатор доступа тип0 this[тип1 пар1, тип2 пар2,…, типN парN] { спецификатор доступа set { } } В этой схеме: тип0 – тип, возвращаемый индексатором; тип1, тип2,…,типN – типы формальных параметров, принимаемых индексатором; пар1, пар2,…,парN – имена формальных параметров. Спецификатор доступа можно опустить, тогда буде использован спецификатор по умолчанию private. Индексаторы не могут быть статическими так, как они задумывались исключительно для работы с объектами классов, а не с самими классами. Индексатор должен принимать хотя бы один параметр, иначе обращение к нему нельзя будет отличить от обращения к объекту. Индексаторы – это еще один удобный способ записи функций, поэтому индексаторы можно подобно функциям перегружать. class SampleCollection { private int[] arr = new int[100]; public int this[int i] { get { return arr[i]; } set { arr[i] = value; } } } Лист. 8.19 Приведем нестандартный пример с перегрузкой индексаторов для доступа к двумерному массиву вещественных чисел. class DoubleMatrixAccess { // поле, хранящее матрицу private double[, ] Matrix; // конструктор класса public DoubleMatrixAccess(int M, int N) { Matrix = new double[M, N]; } // свойство для доступа к количеству строк матрицы public int M { get { return (Matrix.GetLength(0)); } } // свойство для доступа к количеству столбцов матрицы public int N { get { return (Matrix.GetLength(1)); } } // индексатор для доступа к элментам матрицы public double this[int i, int j] { set { if (i >= M || j >= N || i < 0 || j < 0) { Console.WriteLine("Ошибка: Выход за границы массива."); return; } Matrix[i, j] = value; } get
if (i >= M || j >= N || i < 0 || j < 0) { Console.WriteLine("Ошибка: Выход за границы массива."); return 0; } return Matrix[i, j]; } } // индексатор для доступа к элментам матрицы public double this[string i, string j] { set { int IntI, IntJ; if (!Int32.TryParse(i, out IntI)|| ! Int32.TryParse(j, out IntJ)) { Console.WriteLine("Ошибка: Неверное представление числа."); return; } if (IntI >= M || IntJ >= N || IntI < 0 || IntJ < 0) { Console.WriteLine("Ошибка: Выход за границы массива."); return; } Matrix[IntI, IntJ] = value; } get
int IntI, IntJ; if (!Int32.TryParse(i, out IntI) || !Int32.TryParse(j, out IntJ)) { Console.WriteLine("Ошибка: Неверное представление числа."); return 0; } if (IntI >= M || IntJ >= N || IntI < 0 || IntJ < 0) { Console.WriteLine("Ошибка: Выход за границы массива."); return 0; } return Matrix[IntI, IntJ]; } } } Лист. 8.20 В приведенном листинге определен класс DoubleMatrixAccess, у этого класса только одно private поле, представленное двумерным массивом вещественных чисел double[] Matrix, и единственный конструктор, ожидающий два параметра типа int, определяющих размер массива Matrix. В классе DoubleMatrixAccess определены два public свойства для доступа к размерностям матрицы Matrix: свойство M типа int возвращает число строк массива, свойство N типа int возвращает число столбцов массива. В классе DoubleMatrixAccess определены два индексатора для доступа к матрице Matrix. Оба индексатора получают в качестве параметров координаты элемента матрицы, к которому мы хотим обратиться и если координаты, переданные индексатору, не выходят за границы массива, то мы можем получить или изменить нужный элемент, иначе индексатор сообщает об ошибке. Единственная разница между индексаторами состоит в том, что один из них ожидает координаты в числовой форме, а другой ожидает текстовое представление, предаваемых ему координат и уже сам переводит текстовое представления числа в само число. Создадим теперь программу для тестирования класса DoubleMatrixAccess. class Program { static void Main(string[] args) { DoubleMatrixAccess Matrix = new DoubleMatrixAccess(10, 10); // пытаемся обратиться к несуществующим элментам массива Matrix[10, 10] = 1; Matrix[11, 11] = 100; Matrix[10.ToString(), 10.ToString()] = 0; Matrix["7", "11"] = 0; // инициалиизируем массив for (int i = 0; i < Matrix.M - 5; i++) for (int j = 0; j < Matrix.N; j++) Matrix[i, j] = i + j; for (int i = Matrix.M - 5; i < Matrix.M; i++) for (int j = 0; j < Matrix.N; j++) Matrix[i.ToString(), j.ToString()] = i + j; // выводим массив for (int i = 0; i < Matrix.M - 5; i++) { for (int j = 0; j < Matrix.N; j++) Console.Write(Matrix[i, j] + "\t"); Console.WriteLine(); } for (int i = Matrix.M - 5; i < Matrix.M; i++) { for (int j = 0; j < Matrix.N; j++) Console.Write(Matrix[i.ToString(), j.ToString()] + "\t"); Console.WriteLine(); } } } Лист. 8.21 В первой строчке приведенной программы создается объект Matrix класса DoubleMatrixAccess, конструктору класса передаются две размерности поля Matrix этого класса, при создании массива все его элементы обнуляются. Далее в двух циклах в класс Matrix заносятся значения элементов массива, в первом цикле используется числовой индексатор во втором строковой. Затем также в двух циклах элементы массива выводятся из Matrix, в первом цикле используется числовой индексатор во втором строковой. Вывод программы: Ошибка: Выход за границы массива. Ошибка: Выход за границы массива. Ошибка: Выход за границы массива. Ошибка: Выход за границы массива. 0 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 10 2 3 4 5 6 7 8 9 10 11 3 4 5 6 7 8 9 10 11 12 4 5 6 7 8 9 10 11 12 13 5 6 7 8 9 10 11 12 13 14 6 7 8 9 10 11 12 13 14 15 7 8 9 10 11 12 13 14 15 16 8 9 10 11 12 13 14 15 16 17 9 10 11 12 13 14 15 16 17 18 Вывод. 8.7 Индексаторы являются всего лишь удобным средством записи экземплярные методов. Следовательно, для индексаторов не требуются связанные с ними массивы, но благодаря индексаторам можно эмулировать массивы. Фактически определенные таким образом индексаторы перегружают оператор “[]”, перегрузить который в C# явно невозможно. Для примера создадим логическую матрицу, элементы которой равны произведению номера строки и столбца, на которых они находятся. class LogicalMatrix { public int this[int i, int j] { get { return i *j; } } } Лист. 8.22 Единственным членом приведенного класса LogicalMatrix является индексатор, возвращающий произведение переданных ему чисел. Напишем теперь программу для тестирования класса LogicalMatrix. class Program { static void Main(string[] args) { LogicalMatrix Matrix = new LogicalMatrix(); for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) Console.Write(Matrix[i, j] + "\t"); Console.WriteLine(); } } } Лист. 8.23 Это программа сначала создает “матрицу” LogicalMatrix, а затем выводит все её элементы. Вывод программ: 0 0 0 0 0 0 0 0 0 0 0 1 2 3 4 5 6 7 8 9 0 2 4 6 8 10 12 14 16 18 0 3 6 9 12 15 18 21 24 27 0 4 8 12 16 20 24 28 32 36 0 5 10 15 20 25 30 35 40 45 0 6 12 18 24 30 36 42 48 54 0 7 14 21 28 35 42 49 56 63 0 8 16 24 32 40 48 56 64 72 0 9 18 27 36 45 54 63 72 81 Вывод. 8.8 Download 2.46 Mb. Do'stlaringiz bilan baham: |
ma'muriyatiga murojaat qiling