Generic cached IEnumerable I've an IEnumerable&lt;T&gt; source which takes time to generate each item. Once an item is generated, I want to cache it to avoid recomputing the same thing. I want to separate out caching logic from original source.

A few things that bother me are:


Where should I have _cache? In CachedEnumerable or CacheEnumerator?
Thread safety in adding into cache.
Reinventing? Any existing .NET or other library which does this.
Why Dispose in IEnumerator? Should I be doing something there? _cache nuke?




class CachedEnumerable&lt;T&gt; : IEnumerable&lt;T&gt;
{
    private IList&lt;T&gt; _cache = new List&lt;T&gt;();
    IEnumerator&lt;T&gt; _cacheEnumerator = null;
    IEnumerable&lt;T&gt; _source = null;

    public CachedEnumerable(IEnumerable&lt;T&gt; source)
    {
        _source = source;
        _cacheEnumerator = _source.GetEnumerator();
    }

    public IEnumerator&lt;T&gt; GetEnumerator()
    {
        return new CachedEnumerator&lt;T&gt;(_cache, _cacheEnumerator);
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

class CachedEnumerator&lt;T&gt; : IEnumerator&lt;T&gt;
{
    private IList&lt;T&gt; _cache;
    private IEnumerator&lt;T&gt; _source;
    private T _current;
    private int _index;
    private bool _moveNextStatus;

    public CachedEnumerator(IList&lt;T&gt; cache, IEnumerator&lt;T&gt; source)
    {
        _cache = cache;
        _source = source;
        Reset();
    }

    public T Current
    {
        get
        {
            if (_moveNextStatus)
            {
                return _current;
            }
            else
            {
                throw new InvalidOperationException();
            }
        }
    }

    public void Dispose()
    {
        _source.Dispose();
    }

    object System.Collections.IEnumerator.Current
    {
        get { return Current; }
    }

    public bool MoveNext()
    {
        _moveNextStatus = _MoveNext();
        return _moveNextStatus;
    }

    private bool _MoveNext()
    {
        _index++;

        if (_index &lt; _cache.Count)
        {
            _current = _cache[_index];
            return true;
        }
        else
        {
            if (_source.MoveNext())
            {
                _current = _source.Current;
                _cache.Add(_current);
                return true;
            }
            else
            {
                return false;
            }
        }
    }

    public void Reset()
    {
        _index = -1;
        _current = default(T);
        _moveNextStatus = false;
    }
}
You need to access _cache in both classes, so it makes sense to have it as field in both of them too.
Your code is not thread safe. If you wanted to make it thread safe, I think the best solution would be to have a lock that you use whenever you access _cache or _source.
I don't think anything like this is in .Net.
What you're currently doing in Dispose() is wrong. You can't call Dispose() on _source and expect to use it later in another enumerator. In your case, I think you shouldn't do anything in Dispose(). You certainly shouldn't “nuke” _cache, because you're going to need it later!