I've an IEnumerable<T> 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<T> : IEnumerable<T>{    private IList<T> _cache = new List<T>();    IEnumerator<T> _cacheEnumerator = null;    IEnumerable<T> _source = null;    public CachedEnumerable(IEnumerable<T> source)    {        _source = source;        _cacheEnumerator = _source.GetEnumerator();    }    public IEnumerator<T> GetEnumerator()    {        return new CachedEnumerator<T>(_cache, _cacheEnumerator);    }    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()    {        return GetEnumerator();    }}class CachedEnumerator<T> : IEnumerator<T>{    private IList<T> _cache;    private IEnumerator<T> _source;    private T _current;    private int _index;    private bool _moveNextStatus;    public CachedEnumerator(IList<T> cache, IEnumerator<T> 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 < _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;    }}
Generic cached IEnumerable
c#;.net;linq;cache;ienumerable