Caching Sequences: Quick and Dirty

In F# we have this wonderful Seq.cache function which allows us to cache the results of a Seq object (also known as IEnumerable). Unfortunately, C# has no such function, and implementing it yourself usually involves implementing an extra class to hold the data.

Recently, I figured out a way to do this using a few simple functions. Here it is:

public static IEnumerable<T> Cache<T>(this IEnumerable<T> source)
{
    return CacheHelper(source.GetEnumerator());
}

private static IEnumerable<T> CacheHelper<T>(IEnumerator<T> source)
{
    var isEmpty = new Lazy<bool>(() => !source.MoveNext());
    var head = new Lazy<T>(() => source.Current);
    var tail = new Lazy<IEnumerable<T>>(() => CacheHelper(source));

    return CacheHelper(isEmpty, head, tail);
}

private static IEnumerable<T> CacheHelper<T>(
    Lazy<bool> isEmpty, 
    Lazy<T> head, 
    Lazy<IEnumerable<T>> tail)
{
    if (isEmpty.Value)
        yield break;

    yield return head.Value;
    foreach (var value in tail.Value)
        yield return value;
}

Enjoy,
YellPika

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s