Полное руководство. С# 4.0 - Шилдт Герберт
Шрифт:
Интервал:
Закладка:
Свойство Length может быть установлено только из кода в его классе, посколькуего аксессор set объявлен как private. А изменять свойство Length за пределамиего класса не разрешается. Это означает, что за пределами своего класса свойство, посуществу, оказывается доступным только для чтения. Аналогичным образом можнообъявить и свойство Error, как показано ниже.public bool Error { get; private set; }
Благодаря этому свойство Error становится доступным для чтения, но не для установки за пределами класса FailSoftArray.
Для опробования автоматически реализуемых вариантов свойств Length и Errorв классе FailSoftArray удалим сначала переменные len и ErrFlag, поскольку онибольше не нужны, а затем заменим каждое применение переменных len и ErrFlagсвойствами Length и Error в классе FailSoftArray. Ниже приведен обновленныйвариант класса FailSoftArray вместе с методом Main(), демонстрирующим егоприменение.// Применить автоматически реализуемые и доступные// только для чтения свойства Length и Error.using System;class FailSoftArray { int[] a; // ссылка на базовый массив // Построить массив по заданному размеру. public FailSoftArray(int size) { a = new int [size]; Length = size; } // Автоматически реализуемое и доступное только для чтения свойство Length. public int Length { get; private set; } // Автоматически реализуемое и доступное только для чтения свойство Error. public bool Error { get; private set; } // Это индексатор для массива FailSoftArray. public int this[int index] { // Это аксессор get. get { if(ok(index)) { Error = false; return a[index]; } else { Error = true; return 0; } } // Это аксессор set. set { if(ok(index)) { a[index] = value; Error = false; } else Error = true; } } // Возвратить логическое значение true, если // индекс находится в установленных границах. private bool ok(int index) { if(index >= 0 & index < Length) return true; return false; }}// Продемонстрировать применение усовершенствованного// отказоустойчивого массива.class FinalFSDemo { static void Main() { FailSoftArray fs = new FailSoftArray(5); // Использовать свойство Error. for(int i=0; i < fs.Length + 1; i++) { fs[i] = i*10; if(fs.Error) Console.WriteLine("Ошибка в индексе " + i); } }}
Этот вариант класса FailSoftArray действует таким же образом, как и предыдущий, но в нем отсутствуют поддерживающие поля, объявляемые явно.
На применение модификаторов доступа в аксессорах накладываются следующиеограничения. Во-первых, действию модификатора доступа подлежит только один аксессор: set или get, но не оба сразу. Во-вторых, модификатор должен обеспечиватьболее ограниченный доступ к аксессору, чем доступ на уровне свойства или индексатора. И наконец, модификатор доступа нельзя использовать при объявлении аксессорав интерфейсе или же при реализации аксессора, указываемого в интерфейсе. (Подробнее об интерфейсах речь пойдет в главе 12.)Применение индексаторов и свойств
В предыдущих примерах программ был продемонстрирован основной принципдействия индексаторов и свойств, но их возможности не были раскрыты в полнуюсилу. Поэтому в завершение этой главы обратимся к примеру класса RangeArray,в котором индексаторы и свойства используются для создания типа массива с пределами индексирования, определяемыми пользователем.
Как вам должно быть уже известно, индексирование всех массивов в C# начинаетсяс нуля. Но в некоторых приложениях индексирование массива удобнее начинать с любой произвольной точки отсчета: с 1 или даже с отрицательного числа, например от-5 и до 5. Рассматриваемый здесь класс RangeArray разработан таким образом, чтобыдопускать подобного рода индексирование массивов.
Используя класс RangeArray, можно написать следующий фрагмент кода.RangeArray rа = new RangeArray(-5, 10); // массив с индексами от -5 до 10for(int i=-5; i <= 10; i++) ra[i] = i; // индексирование массива от -5 до 10
Нетрудно догадаться, что в первой строке этого кода конструируется объект класса RangeArray с пределами индексирования массива от -5 до 10 включительно. Первый аргумент обозначает начальный индекс, а второй — конечный индекс. Как толькообъект rа будет сконструирован, он может быть проиндексирован как массив в пределах от -5 до 10.
Ниже приведен полностью класс RangeArray вместе с классом RangeArrayDemo,в котором демонстрируется индексирование массива в заданных пределах. КлассRangeArray реализован таким образом, чтобы поддерживать массивы типа int, нопри желании вы можете изменить этот тип на любой другой./* Создать класс со специально указываемыми пределами индексирования массива. Класс RangeArray допускает индексирование массива с любого значения, а не только с нуля. При создании объекта класса RangeArray указываются начальный и конечный индексы. Допускается также указывать отрицательные индексы. Например, можно создать массивы, индексируемые от -5 до 5, от 1 до 10 или же от 50 до 56. */using System;class RangeArray { // Закрытые данные. int[] а; // ссылка на базовый массив int lowerBound; // наименьший индекс int upperBound; // наибольший индекс // Автоматически реализуемое и доступное только для чтения свойство Length. public int Length { get; private set; } // Автоматически реализуемое и доступное только для чтения свойство Error. public bool Error { get; private set; } // Построить массив по заданному размеру. public RangeArray(int low, int high) { high++; if(high <= low) { Console.WriteLine("Неверные индексы"); high = 1; // создать для надежности минимально допустимый массив low = 0; } а = new int[high - low]; Length = high - low; lowerBound = low; upperBound = --high; } // Это индексатор для класса RangeArray. public int this[int index] { // Это аксессор get. get { if(ok(index)) { Error = false; return a[index - lowerBound]; } else { Error = true; return 0; } } // Это аксессор set. set { if(ok(index)) { a[index - lowerBound] = value; Error = false; } else Error = true; } } // Возвратить логическое значение true, если // индекс находится в установленных границах. private bool ok(int index) { if(index >= lowerBound & index <= upperBound) return true; return false; }}// Продемонстрировать применение массива с произвольно// задаваемыми пределами индексирования.class RangeArrayDemo { static void Main() { RangeArray ra = new RangeArray(-5, 5); RangeArray ra2 = new RangeArray(1, 10); RangeArray ra3 = new RangeArray(-20, -12); // Использовать объект ra в качестве массива. Console.WriteLine("Длина массива ra: " + rа.Length); for(int i = -5; i <= 5; i++) ra[i] = i; Console.Write("Содержимое массива ra: "); for(int i = -5; i <= 5; i++) Console.Write(ra[i] + " "); Console.WriteLine("n"); // Использовать объект ra2 в качестве массива. Console.WriteLine("Длина массива ra2: " + ra2.Length); for(int i = 1; i <= 10; i++) ra2[i] = i; Console.Write("Содержимое массива ra2: "); for(int i = 1; i <= 10; i++) Console.Write(ra2[i] + " "); Console.WriteLine("n"); // Использовать объект raЗ в качестве массива. Console.WriteLine("Длина массива ra3: " + ra3.Length); for(int i = -20; i <= -12; i++) ra3[i] = i; Console.Write("Содержимое массива ra3: "); for(int i = -20; i <= -12; i++) Console.Write(ra3[i] + " "); Console.WriteLine("n"); }}
При выполнении этого кода получается следующий результат.Длина массива ra: 11Содержимое массива ra: -5 -4 -3 -2 -1 0 1 2 3 4 5Длина массива ra2: 10Содержимое массива ra2: 1 2 3 4 5 6 7 8 9 10Длина массива ra3: 9Содержимое массива ra2: -20 -19 -18 -17 -16 -15 -14 -13 -12
Как следует из результата выполнения приведенного выше кода, объекты типаRangeArray можно индексировать в качестве массивов, начиная с любой точки отсчета, а не только с нуля. Рассмотрим подробнее саму реализацию классаRangeArray.
В начале класса RangeArray объявляются следующие закрытые переменные экземпляра.// Закрытые данные.int[] а; // ссылка на базовый массивint lowerBound; // наименьший индексint upperBound; // наибольший индекс