// Needed for NET40 #if !NET_4_6 using System; using System.Collections.Generic; using System.Linq; namespace LinqInternal.Collections { [Serializable] [System.Diagnostics.DebuggerNonUserCode] internal partial class ProgressiveCollection : IReadOnlyCollection, ICollection { private readonly ICollection _cache; private readonly IEqualityComparer _comparer; private readonly Progressor _progressor; public ProgressiveCollection(IEnumerable wrapped) : this(wrapped, new HashSet(), null) { // Empty } public ProgressiveCollection(Progressor wrapped) : this(wrapped, new HashSet(), null) { // Empty } public ProgressiveCollection(IEnumerable wrapped, IEqualityComparer comparer) : this(wrapped, new HashSet(comparer), comparer) { // Empty } public ProgressiveCollection(Progressor wrapped, IEqualityComparer comparer) : this(wrapped, new HashSet(comparer), comparer) { // Empty } protected ProgressiveCollection(IEnumerable wrapped, ICollection cache, IEqualityComparer comparer) { if (cache == null) { throw new ArgumentNullException("cache"); } _cache = cache; _progressor = new Progressor(wrapped); _progressor.SubscribeAction(obj => _cache.Add(obj)); _comparer = comparer ?? EqualityComparer.Default; } protected ProgressiveCollection(Progressor wrapped, ICollection cache, IEqualityComparer comparer) { if (cache == null) { throw new ArgumentNullException("cache"); } if (wrapped == null) { throw new ArgumentNullException("cache"); } _cache = cache; _progressor = new Progressor(wrapped); _progressor.SubscribeAction(obj => _cache.Add(obj)); _comparer = comparer ?? EqualityComparer.Default; } protected ProgressiveCollection(TryTake tryTake, ICollection cache, IEqualityComparer comparer) { if (cache == null) { throw new ArgumentNullException("cache"); } _cache = cache; _progressor = new Progressor(tryTake, false); // false because the underlaying structure may change _progressor.SubscribeAction(obj => _cache.Add(obj)); _comparer = comparer ?? EqualityComparer.Default; } public int Count { get { _progressor.AsEnumerable().Consume(); return _cache.Count; } } public bool EndOfEnumeration { get { return _progressor.IsClosed; } } bool ICollection.IsReadOnly { get { return true; } } protected IEqualityComparer Comparer { get { return _comparer; } } protected Progressor Progressor { get { return _progressor; } } public void Close() { _progressor.Close(); } public bool Contains(T item) { if (CacheContains(item)) { return true; } T found; while (_progressor.TryTake(out found)) { if (_comparer.Equals(item, found)) { return true; } } return false; } public bool Contains(T item, IEqualityComparer comparer) { return Enumerable.Contains(this, item, comparer); } public void CopyTo(T[] array) { _progressor.AsEnumerable().Consume(); _cache.CopyTo(array, 0); } public void CopyTo(T[] array, int arrayIndex) { _progressor.AsEnumerable().Consume(); _cache.CopyTo(array, arrayIndex); } public void CopyTo(T[] array, int arrayIndex, int countLimit) { Extensions.CanCopyTo(array, arrayIndex, countLimit); _progressor.While(() => _cache.Count < countLimit).Consume(); _cache.CopyTo(array, arrayIndex, countLimit); } public IEnumerator GetEnumerator() { foreach (var item in _cache) { yield return item; } { T item; while (_progressor.TryTake(out item)) { yield return item; } } } void ICollection.Add(T item) { throw new NotSupportedException(); } void ICollection.Clear() { throw new NotSupportedException(); } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); } bool ICollection.Remove(T item) { throw new NotSupportedException(); } protected virtual bool CacheContains(T item) { return _cache.Contains(item, _comparer); } } } #endif