Skip to content

Instantly share code, notes, and snippets.

@michaelgwelch
Created July 7, 2011 14:47
Show Gist options
  • Save michaelgwelch/1069667 to your computer and use it in GitHub Desktop.
Save michaelgwelch/1069667 to your computer and use it in GitHub Desktop.
C# Iterator interface
using System.Collections.Generic;
namespace CollectionsExtensions
{
public static class EnumerableExtensions
{
/// <summary>
/// Provides an extension method that gets an iterator for
/// IEnumerables. This makes it as easy to get an iterator as it
/// is to get an enumerator.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="enumerable"></param>
/// <returns></returns>
public static IIterator<T> GetIterator<T>(this IEnumerable<T> enumerable)
{
return EnumeratorIterator<T>.GetIterator(enumerable);
}
}
}
using System.Collections.Generic;
namespace CollectionsExtensions
{
/// <summary>
/// Defines an implementation of <see cref="IIterator{T}"/> that
/// works on any <see cref="IEnumerable{T}"/> instance by wrapping
/// its enumerator.
/// </summary>
public class EnumeratorIterator<T> : IIterator<T>
{
private readonly IEnumerator<T> enumerator;
private bool hasCurrent;
public bool HasCurrent
{
get { return hasCurrent; }
}
public T Current
{
get { return enumerator.Current; }
}
public void MoveNext()
{
hasCurrent = enumerator.MoveNext();
}
private EnumeratorIterator(IEnumerator<T> enumerator)
{
this.enumerator = enumerator;
this.hasCurrent = enumerator.MoveNext();
}
/// <summary>
/// Gets an iterator for the specified enumerable.
/// </summary>
/// <param name="enumerable"></param>
/// <returns></returns>
public static IIterator<T> GetIterator(IEnumerable<T> enumerable)
{
return new EnumeratorIterator<T>(enumerable.GetEnumerator());
}
public void Dispose()
{
enumerator.Dispose();
}
}
}
using System;
namespace CollectionsExtensions
{
/// <summary>
/// Defines methods for iteratating over a collection.
/// </summary>
/// <remarks>
/// Sometimes it's advantageous to have a HasCurrent property. This
/// interface differs from <see cref="IEnumerator{T}>"/> in that
/// <see cref="MoveNext"/> has no return value, and the value it would
/// have returned is accessible from <see cref="HasCurrent"/>
/// property.
/// </remarks>
public interface IIterator<out T> : IDisposable
{
bool HasCurrent { get; }
T Current { get; }
void MoveNext();
}
}
using System;
using System.Linq;
namespace CollectionsExtensions
{
public class Program
{
public static void Main()
{
var array = new [] { 1, 3, 5, 7, 11, 13, 17, 19 };
// ridiculous example - since this could be simplified
// by using foreach and an enumerator.
var iterator = array.GetIterator();
while (iterator.HasCurrent)
{
Console.WriteLine(iterator.Current);
iterator.MoveNext();
}
iterator = Enumerable.Empty<int>().GetIterator();
while (iterator.HasCurrent)
{
Console.WriteLine(iterator.Current);
iterator.MoveNext();
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment