Итератор (Iterator)

Шаблон Итератор обеспечивает последовательный доступ ко всем элементам коллекции, не раскрывая при этом её внутренней реализации. Задача итератора – упростить обход и сделать его однообразным для коллекций различных типов. Причём реализация шаблона может находиться как в объекте, представляющим коллекции, так и отдельно от него.

В шаблоне Итератор задействованы следующие участники. Интерфейс итератора определяет методы для доступа к элементам коллекций. Итератор – класс, реализующий интерфейс итератора для конкретной коллекции. Интерфейс составного объекта (коллекции) задаёт способ получения итератора клиентом. Наконец, составной объект – это реализация интерфейса коллекции.

Обычно интерфейс итератора состоит из следующих операций:

Reset() – устанавливает первый элемент коллекции в качестве текущего;

MoveNext() – переход на следующий элемент;

IsDone – проверяет, есть ли ещё элементы в коллекции;

Current – возвращает текущий элемент.

Этот список можно изменять. Например, объединить MoveNext() и IsDone в один метод. Или добавить метод Skip(), позволяющий пропустить заданное число элементов. В некоторых случаях может быть полезно свойство, содержащее ссылку на предыдущий элемент.

Разберём пример реализации шаблона Итератор. Вначале опишем интерфейс итератора:

public interface IIterator<out T>

{

void Reset();

void MoveNext();

bool IsDone { get; }

T Current { get; }

}

Далее представим интерфейс коллекции:

public interface IContainer<out T>

{

IIterator<T> CreateIterator();

}

Сконструируем коллекцию, реализующую интерфейс IContainer<T>. При помощи вложенного класса реализуем итератор коллекции:

public class ListContainer: IContainer<int>

{

private readonly int[] _list;

public class ForwardIterator: IIterator<int>

{

private readonly int[] _iteratorList;

private int _position;

public ForwardIterator(int[] list)

{

_iteratorList = new int[list.Length];

list.CopyTo(_iteratorList, 0);

}

public void Reset()

{

_position = 0;

}

public void MoveNext()

{

_position++;

}

public bool IsDone

{

get { return _position > _iteratorList.Length - 1; }

}

public int Current

{

get { return _iteratorList[_position]; }

}

}

public ListContainer(params int[] data)

{

_list = new int[data.Length];

data.CopyTo(_list, 0);

}

public IIterator<int> CreateIterator()

{

return new ForwardIterator(_list);

}

}

Применить описанные классы и интерфейсы можно следующим образом:

IContainer<int> list = new ListContainer(2, 3, 5, 7);

var iterator = list.CreateIterator();

while (!iterator.IsDone)

{

Console.WriteLine(iterator.Current);

iterator.MoveNext();

}

Поддержка итераторов реализована на платформе.NET и в синтаксисе языка C# при помощи интерфейсов IEnumerable и IEnumerator, операторов yield и foreach. При этом IEnumerator играет роль интерфейса итератора, а IEnumerable выступает в качестве интерфейса составного объекта.


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: