using System; using System.Collections.Generic; using MemoryPools.Collections.Specialized; namespace MemoryPools.Collections.Linq { internal class DistinctExprEnumerable : IPoolingEnumerable { private int _count; private IPoolingEnumerator _parent; private IEqualityComparer _comparer; private Func _selector; public DistinctExprEnumerable Init(IPoolingEnumerator parent, Func selector, IEqualityComparer comparer = default) { _parent = parent; _selector = selector; _comparer = comparer; _count = 0; return this; } public IPoolingEnumerator GetEnumerator() { _count++; return Pool.Get().Init(this, _parent, _selector, _comparer); } private void Dispose() { if(_count == 0) return; _count--; if (_count == 0) { _parent?.Dispose(); _parent = default; _selector = default; Pool>.Return(this); } } internal class DistinctExprEnumerator : IPoolingEnumerator { private IPoolingEnumerator _src; private Func _selector; private PoolingDictionary _hashset; private DistinctExprEnumerable _parent; public DistinctExprEnumerator Init( DistinctExprEnumerable parent, IPoolingEnumerator src, Func selector, IEqualityComparer comparer) { _src = src; _parent = parent; _selector = selector; _hashset = Pool>.Get().Init(0, comparer ?? EqualityComparer.Default); return this; } public bool MoveNext() { while (_src.MoveNext()) { var key = _selector(_src.Current); if(_hashset.ContainsKey(key)) continue; _hashset[key] = 1; return true; } return false; } public void Reset() => _src.Reset(); object IPoolingEnumerator.Current => Current!; public T Current => _src.Current; public void Dispose() { _parent?.Dispose(); _parent = default!; _hashset?.Dispose(); _hashset = default!; _src = default!; _selector = default!; Pool.Return(this); } } IPoolingEnumerator IPoolingEnumerable.GetEnumerator() => GetEnumerator(); } }