Skip to content

Instantly share code, notes, and snippets.

@SimonPStevens
Created July 8, 2017 21:13
Show Gist options
  • Save SimonPStevens/2ab32aca5ee319894ee841f6072cec1b to your computer and use it in GitHub Desktop.
Save SimonPStevens/2ab32aca5ee319894ee841f6072cec1b to your computer and use it in GitHub Desktop.
An enumerable extension that can be used to ensure an IEnumerable<T> is only evaulated once.
namespace System.Collections.Generic
{
public static class RunOnceEnumerableExtensions
{
public static IRunOnceEnumerable<T> OnlyRunOnce<T>(this IEnumerable<T> source)
{
return new RunOnceEnumerable<T>(source);
}
public interface IRunOnceEnumerable<T> : IEnumerable<T>
{
}
private class RunOnceEnumerable<T> : IRunOnceEnumerable<T>
{
private IEnumerable<T> enumerable;
private IEnumerator<T> enumerator;
int indexedUpTo;
private List<T> data = new List<T>();
public RunOnceEnumerable(IEnumerable<T> enumerable)
{
this.enumerable = enumerable;
this.enumerator = enumerable.GetEnumerator();
}
public IEnumerator<T> GetEnumerator()
{
int currentIndex = 0;
bool isMoreData = true;
do
{
if (currentIndex < indexedUpTo)
{
yield return data[currentIndex];
}
else
{
if (isMoreData = enumerator.MoveNext())
{
indexedUpTo++;
data.Add(enumerator.Current);
yield return enumerator.Current;
}
}
currentIndex++;
} while (isMoreData);
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment