Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
CSharp Language Specification.doc
Скачиваний:
12
Добавлен:
26.09.2019
Размер:
4.75 Mб
Скачать

10.9Индексаторы

Индексатор является членом, дающим возможность индексировать объект так же, как массив. Индексаторы объявляются с помощью объявлений_индексаторов:

объявление_индексатора: атрибутынеоб модификаторы_индексаторанеоб декларатор_индексатора { объявления_методов_доступа }

модификаторы_индекса: модификатор_индекса модификаторы_индекса модификатор_индекса

модификатор_индекса: new public protected internal private virtual sealed override abstract extern

декларатор_индексатора: тип this [ список_формальных_параметров ] тип тип_интерфейса . this [ список_формальных_параметров ]

Объявление_индексатора может включать набор атрибутов (§17) и допустимое сочетание из четырех модификаторов доступа (§10.3.5) и модификаторы new (§10.3.4), virtual (§10.6.3), override (§10.6.4), sealed (§10.6.5), abstract (§10.6.6) и extern (§10.6.7).

Объявления индексаторов подчиняются тем же правилам, что и объявления методов (§10.6), в отношении допустимых сочетаний модификаторов, с одним исключением – модификатор static не допускается в объявлении индексатора.

Модификаторы virtual, override и abstract являются взаимоисключающими, кроме как в одном случае. Модификаторы abstract и override могут использоваться совместно, так чтобы абстрактный индексатор мог переопределить виртуальный.

Тип в объявлении индексатора указывает тип элемента индексатора, вводимого объявлением. Если только индексатор не является явной реализацией члена интерфейса, за типом следует зарезервированное слово this. Для явной реализации члена интерфейса за типом следует тип_интерфейса, «.» и зарезервированное слово this. В отличие от других членов, индексаторы не имеют имен, определяемых пользователем.

Список_формальных_параметров указывает параметры индексатора. Список формальных параметров индексатора соответствует списку формальных параметров метода (§10.6.1), кроме того, что по крайней мере один параметр должен быть указан, а модификаторы параметров ref и out не разрешены.

Тип индексатора и каждый из типов, на которые есть ссылки в списке_формальных_параметров, должны быть по крайней мере так же доступными, как сам индексатор (§3.5.4).

Объявления_методов_доступа (§10.7.2), которые должны быть заключены в лексемы «{" и "}», объявляют методы доступа индексатора. Методы доступа указывают исполняемые операторы, связанные с чтением и записью элементов индексатора.

Хотя синтаксис доступа к элементу индексатора такой же, как синтаксис доступа к элементу массива, элемент индексатора не классифицируется как переменная. Так, невозможно передать элемент индексатора в качестве аргумента ref или out.

Список формальных параметров индексатора определяет подпись (§3.6) индексатора. В частности, подпись индексатора состоит из числа и типов его формальных параметров. Тип элемента и имена формальных параметров не являются частью сигнатуры индексатора.

Сигнатура индексатора должна отличаться от сигнатур всех других индексаторов, объявленных в этом же классе.

Понятия индексаторов и свойств очень схожи, но отличаются следующим:

  • свойство идентифицируется своим именем, а индексатор идентифицируется своей подписью;

  • доступ к свойству производится через простое_имя (§7.6.2) или доступ_к_члену (§7.6.4), а доступ к элементу индексатора производится через доступ_к_элементу (§7.6.6.2);

  • свойство может быть static членом, а индексатор всегда является членом экземпляра;

  • метод доступа get свойства соответствует методу без параметров, тогда как метод доступа get индексатора соответствует методу с тем же списком формальных параметров, что у индексатора;

  • метод доступа set свойства соответствует методу с одним параметром с именем value, тогда как метод доступа set индексатора соответствует методу с тем же списком формальных параметров, что у индексатора, плюс дополнительный параметр с именем value;

  • объявление в методе доступа к индексатору локальной переменной с тем же именем, что и параметр индексатора, является ошибкой времени компиляции;

  • в объявлении переопределяющего свойства при обращении к унаследованному свойству используется синтаксис base.P, где P – имя свойства. В объявлении переопределяющего индексатора при обращении к унаследованному индексатору используется синтаксис base[E], где E – список выражений, разделенных запятыми.

За исключением этих различий, все правила, определенные в §10.7.2 и §10.7.3, применяются к методам доступа к индексатору, а также к методам доступа к свойствам.

Если в объявление индексатора включен модификатор extern, индексатор называется внешним индексатором. Так как объявление внешнего индексатора не предоставляет фактической реализации, каждое из его объявлений_метода_доступа состоит из точки с запятой.

В примере внизу объявлен класс BitArray, реализующий индексатор для доступа к отдельным битам в битовом массиве.

using System;

class BitArray { int[] bits; int length;

public BitArray(int length) { if (length < 0) throw new ArgumentException(); bits = new int[((length - 1) >> 5) + 1]; this.length = length; }

public int Length { get { return length; } }

public bool this[int index] { get { if (index < 0 || index >= length) { throw new IndexOutOfRangeException(); } return (bits[index >> 5] & 1 << index) != 0; } set { if (index < 0 || index >= length) { throw new IndexOutOfRangeException(); } if (value) { bits[index >> 5] |= 1 << index; } else { bits[index >> 5] &= ~(1 << index); } } } }

Экземпляр класса BitArray расходует существенно меньше памяти, чем соответствующий bool[] (так как каждое значение первого занимает только один бит, тогда как у второго – один байт), но позволяет выполнять те же операции, что и bool[].

В следующем классе CountPrimes используется BitArray и классический алгоритм «решето» для вычисления количества простых чисел между 1 и заданным максимумом.

class CountPrimes { static int Count(int max) { BitArray flags = new BitArray(max + 1); int count = 1; for (int i = 2; i <= max; i++) { if (!flags[i]) { for (int j = i * 2; j <= max; j += i) flags[j] = true; count++; } } return count; }

static void Main(string[] args) { int max = int.Parse(args[0]); int count = Count(max); Console.WriteLine("Found {0} primes between 1 and {1}", count, max); } }

Обратите внимание, что синтаксис обращения к элементам BitArray точно такой же, как для bool[].

В следующем примере показан класс сетки 26  10 с индексатором с двумя параметрами. Первым параметром должна быть буква верхнего или нижнего регистра в диапазоне A–Z, а вторым – целое число в диапазоне 0–9.

using System;

class Grid { const int NumRows = 26; const int NumCols = 10;

int[,] cells = new int[NumRows, NumCols];

public int this[char c, int col] { get { c = Char.ToUpper(c); if (c < 'A' || c > 'Z') { throw new ArgumentException(); } if (col < 0 || col >= NumCols) { throw new IndexOutOfRangeException(); } return cells[c - 'A', col]; }

set { c = Char.ToUpper(c); if (c < 'A' || c > 'Z') { throw new ArgumentException(); } if (col < 0 || col >= NumCols) { throw new IndexOutOfRangeException(); } cells[c - 'A', col] = value; } } }

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]