Usage examples: The pattern is very common in C# code. Many frameworks and libraries use it to provide a standard way for traversing their collections.
Identification: Iterator is easy to recognize by the navigation methods (such as next, previous and others). Client code that uses iterators might not have direct access to the collection being traversed.
Conceptual Example
This example illustrates the structure of the Iterator design pattern. It focuses on answering these questions:
What classes does it consist of?
What roles do these classes play?
In what way the elements of the pattern are related?
Program.cs: Conceptual example
usingSystem;usingSystem.Collections;usingSystem.Collections.Generic;namespaceRefactoringGuru.DesignPatterns.Iterator.Conceptual{abstractclassIterator:IEnumerator {objectIEnumerator.Current =>Current(); // Returns the key of the current elementpublicabstractintKey(); // Returns the current elementpublicabstractobjectCurrent(); // Move forward to next elementpublicabstractboolMoveNext(); // Rewinds the Iterator to the first elementpublicabstractvoidReset(); }abstractclassIteratorAggregate:IEnumerable { // Returns an Iterator or another IteratorAggregate for the implementing // object.publicabstractIEnumeratorGetEnumerator(); } // Concrete Iterators implement various traversal algorithms. These classes // store the current traversal position at all times.classAlphabeticalOrderIterator:Iterator {privateWordsCollection _collection; // Stores the current traversal position. An iterator may have a lot of // other fields for storing iteration state, especially when it is // supposed to work with a particular kind of collection.privateint _position =-1;privatebool _reverse =false;publicAlphabeticalOrderIterator(WordsCollection collection,bool reverse =false) {this._collection= collection;this._reverse= reverse;if (reverse) {this._position=collection.getItems().Count; } }publicoverrideobjectCurrent() {returnthis._collection.getItems()[_position]; }publicoverrideintKey() {returnthis._position; }publicoverrideboolMoveNext() {int updatedPosition =this._position+ (this._reverse?-1:1);if (updatedPosition >=0&& updatedPosition <this._collection.getItems().Count) {this._position= updatedPosition;returntrue; }else {returnfalse; } }publicoverridevoidReset() {this._position=this._reverse?this._collection.getItems().Count-1:0; } } // Concrete Collections provide one or several methods for retrieving fresh // iterator instances, compatible with the collection class.classWordsCollection:IteratorAggregate {List<string> _collection =newList<string>();bool _direction =false;publicvoidReverseDirection() { _direction =!_direction; }publicList<string> getItems() {return _collection; }publicvoidAddItem(string item) {this._collection.Add(item); }publicoverrideIEnumeratorGetEnumerator() {returnnewAlphabeticalOrderIterator(this, _direction); } }classProgram {staticvoidMain(string[] args) { // The client code may or may not know about the Concrete Iterator // or Collection classes, depending on the level of indirection you // want to keep in your program.var collection =newWordsCollection();collection.AddItem("First");collection.AddItem("Second");collection.AddItem("Third");Console.WriteLine("Straight traversal:");foreach (var element in collection) {Console.WriteLine(element); }Console.WriteLine("\nReverse traversal:");collection.ReverseDirection();foreach (var element in collection) {Console.WriteLine(element); } } }}
Output.txt: Execution result
Straight traversal:
First
Second
Third
Reverse traversal:
Third
Second
First