Преимущество индексатора заключается, в частности, в том, что он позволяет полностью управлять доступом к массиву, избегая нежелательного доступа. В качестве примера рассмотрим программу, в которой создается класс FailSoftArray
, реализующий массив для выявления ошибок нарушения границ массива, а следовательно, для предотвращения исключительных ситуаций, возникающих во время выполнения в связи с индексированием массива за его границами. Для этого массив инкапсулируется в качестве закрытого члена класса, а доступ к нему осуществляется только с помощью индексатора. При таком подходе исключается любая попытка получить доступ к массиву за его границами, причем эта попытка пресекается без катастрофических последствий для программы. А поскольку в классе FailSoftArray
используется индексатор, то к массиву можно обращаться с помощью обычной формы записи.
// Использовать индексатор для создания отказоустойчивого массива.
using System;
class FailSoftArray {
int[] a; // ссылка на базовый массив
public int Length; //открытая переменная длины массива
public bool ErrFlag; // обозначает результат последней операции
// Построить массив заданного размера,
public FailSoftArray(int size) {
a = new int [size] ;
Length = size;
}
// Это индексатор для класса FailSoftArray.
public int this[int index] {
// Это аксессор get.
get {
if (ok(index)) {
ErrFlag = false;
return a[index];
}
else {
ErrFlag = true;
return 0;
}
}
// Это аксессор set.
set {
if(ok(index)) {
a[index] = value;
ErrFlag = false;
}
else
ErrFlag = true;
}
}
// Возвратить логическое значение true, если
// индекс находится в установленных границах,
private bool ok(int index) {
if(index >= 0 & index < Length) return true;
return false;
}
}
// Продемонстрировать применение отказоустойчивого массива,
class FSDemo {
static void Main() {
FailSoftArray fs = new FailSoftArray(5);
int x;
// Выявить скрытые сбои.
Console.WriteLine("Скрытый сбой.");
for(int i=0; i < (fs.Length * 2); i++)
fs[i] = i*10;
for(int i=0; i < (fs.Length * 2); i++) {
x = fs[i] ;
if (x != -1) Console.Write(x + " ") ;
}
Console.WriteLine();
//А теперь показать сбои.
Console.WriteLine("\nСбой с уведомлением об ошибках.");
for(int i=0; i < (fs.Length * 2); i++) {
fs[i] = i * 10;
if(fs.ErrFlag)
Console.WriteLine("fs[" + i + "] вне границ");
}
for(int i=0; i < (fs.Length * 2); i++) {
x = fs [ i ] ;
if(!fs.ErrFlag)
Console.Write(x + " ");
else
Console.WriteLine("fs[" + i + "] вне границ");
}
}
}
Вот к какому результату приводит выполнение этой программы.
Скрытый сбой.
0 10 20 30 40 0 0 0 0 0
Сбой с уведомлением об ошибках.
fs[5] вне границ
fs[6] вне границ
fs[7] вне границ
fs[8] вне границ
fs[9] вне границ
0 10 20 30 40 fs[5] вне границ
fs[6] вне границ
fs[7] вне границ
fs[8] вне границ
fs[9] вне границ
Индексатор препятствует нарушению границ массива. Внимательно проанализируем каждую часть кода индексатора. Он начинается со следующей строки.
public int this[int index] {
В этой строке кода объявляется индексатор, оперирующий элементами типа int. Ему передается индекс в качестве параметра index
. Кроме того, индексатор объявляется открытым (public
), что дает возможность использовать этот индексатор в коде за пределами его класса.
Рассмотрим следующий код аксессора get
.
get {
if (ok(index) ) {