Object Oriented Programming Patterns for Geeks
The Iterator Pattern
namespace ooppatterns
{
using System;
using System.Collections;
using System.Collections.Generic;
internal class Program
{
private static void Main( string[] args )
{
// Create something to enumerate.
List<string> str = new List<string>();
str.AddRange( new string[]
{
".NET",
"Iterators",
"are",
"all",
"you",
"need"
} );
// Demonstrate basic .NET implementation
Console.WriteLine( ".NET c# shortcut syntax" );
Console.WriteLine( new string( '-', 30 ) );
foreach ( string val in str )
Console.WriteLine( val );
// Demonstrate above in longhand (A)
Console.WriteLine( "\nDirect implementation Syntax (A)" );
Console.WriteLine( new string( '-', 30 ) );
for ( IEnumerator<string> enm = str.GetEnumerator(); enm.MoveNext(); )
Console.WriteLine( enm.Current );
// Demonstrate above in longhand (B)
Console.WriteLine( "\nDirect implementation Syntax (B)" );
Console.WriteLine( new string( '-', 30 ) );
IEnumerator<string> enmB = str.GetEnumerator();
while ( enmB.MoveNext() )
Console.WriteLine( enmB.Current );
// Demonstrate the use of a custom enumerator with an added feature.
// the basic .NET implementation uses a .NET 'out-of-the-box' version.
Console.WriteLine( "\nCustom implementation - forward" );
Console.WriteLine( new string( '-', 30 ) );
for ( IEnumerator<string> enm = new myEnum( str, Direction.Forward );
enm.MoveNext();
)
Console.WriteLine( enm.Current );
Console.WriteLine( "\nCustom implementation - backward" );
Console.WriteLine( new string( '-', 30 ) );
for ( IEnumerator<string> enm = new myEnum( str, Direction.Backward );
enm.MoveNext();
)
Console.WriteLine( enm.Current );
// Demonstrate the .NET 2.0 'yield' ability shorthand...
Console.WriteLine( "\n.NET c# shortcut using 'yield' to "
+ @"retrieve INDEX MOD 2 == 0 - forward" );
Console.WriteLine( new string( '-', 30 ) );
foreach ( string val in HandleList.GetMod2EvenForward( str ) )
Console.WriteLine( val );
Console.WriteLine( "\n.NET c# shortcut using 'yield' to "
+ @"retrieve INDEX MOD 2 == 1 - backward" );
Console.WriteLine( new string( '-', 30 ) );
foreach ( string val in HandleList.GetMod2OddBackword( str ) )
Console.WriteLine( val );
// Demonstrate the .NET 2.0 'yield' ability longhand...
Console.WriteLine( "\nCustom implementation using 'yield' to "
+ @"retrieve INDEX MOD 2 == 0 - forward" );
Console.WriteLine( new string( '-', 30 ) );
for ( IEnumerator<string> enm
= HandleList.GetMod2EvenForward( str ).GetEnumerator();
enm.MoveNext();
)
Console.WriteLine( enm.Current );
Console.WriteLine( "\nCustom implementation using 'yield' to "
+ @"retrieve INDEX MOD 2 == 1 - backward" );
Console.WriteLine( new string( '-', 30 ) );
for ( IEnumerator<string> enm
= HandleList.GetMod2OddBackword( str ).GetEnumerator();
enm.MoveNext();
)
Console.WriteLine( enm.Current );
Console.ReadLine();
}
}
enum Direction
{
Forward,
Backward
}
// Custom Enumerator with the added feature to
// allow you to enumerate the contents forwards OR backwards.
class myEnum : IEnumerator<string>
{
private List<string> _collection;
private int _index;
private Direction _direction;
public myEnum( List<string> collection, Direction direction )
{
this._collection = collection;
this._direction = direction;
this.Reset();
}
// This has been added to allow some trickery with
// the 'yield' example.
public int Index
{
get { return this._index; }
}
public string Current
{
get { return this._collection[this._index]; }
}
public void Dispose() { }
object IEnumerator.Current
{
get { return this.Current; }
}
public bool MoveNext()
{
if ( this._direction == Direction.Forward )
{
this._index++;
return this._index < this._collection.Count;
}
else
{
this._index--;
return this._index >= 0;
}
}
public void Reset()
{
if ( this._direction == Direction.Forward )
this._index = -1;
else
this._index = this._collection.Count;
}
}
// Demonstrate the usage of the yield keyword...
// NB: This is really just syntactic sugar supplied by the compiler.
// To see how it is implemented after compilation, please use
// Lutz Roeder's reflector.
static class HandleList
{
public static IEnumerable<string> GetMod2EvenForward( List<string> list )
{
for ( myEnum enm
= new myEnum( list, Direction.Forward );
enm.MoveNext(); )
if ( enm.Index % 2 == 0 )
yield return enm.Current;
}
public static IEnumerable<string> GetMod2OddBackword( List<string> list )
{
for ( myEnum enm
= new myEnum( list, Direction.Backward );
enm.MoveNext(); )
if ( enm.Index % 2 == 1 )
yield return enm.Current;
}
}
}