IEnumerable <T> GetEnumerable <U, V, T> (IEnumerable <U> first, IEnumerable <V> second, TemporaryArea <TKey, Tuple <VSlot <U>, VSlot <V> > > store, Func <U, TKey> fKeySelect, Func <V, TKey> sKeySelect, Func <U, V, T> resultor) { IEnumerator <U> eFirst = first.GetEnumerator(); IEnumerator <V> eSecond = second.GetEnumerator(); try { while (eFirst.MoveNext()) { if (!eSecond.MoveNext()) { yield break; } U e1 = eFirst.Current; V e2 = eSecond.Current; TKey key1 = fKeySelect(e1); TKey key2 = sKeySelect(e2); if (comparer.Equals(key1, key2)) { yield return(resultor(e1, e2)); continue; } Tuple <VSlot <U>, VSlot <V> > kvp; do { if (store.TryRemove(key1, out kvp) && kvp.Item2.HasValue) { yield return(resultor(e1, kvp.Item2.Value)); break; } } while (!store.TryAdd(key1, Tuple.Create(new VSlot <U> (e1), new VSlot <V> ()))); do { if (store.TryRemove(key2, out kvp) && kvp.Item1.HasValue) { yield return(resultor(kvp.Item1.Value, e2)); break; } } while (!store.TryAdd(key2, Tuple.Create(new VSlot <U> (), new VSlot <V> (e2)))); } } finally { eFirst.Dispose(); eSecond.Dispose(); } }
internal override IList <IEnumerable <TResult> > GetEnumerables(QueryOptions options) { var first = Parent.GetEnumerables(options); var second = Second.GetEnumerables(options); if (first.Count != second.Count) { throw new InvalidOperationException("Internal size mismatch"); } var store = new TemporaryArea <TKey, Tuple <VSlot <TFirst>, VSlot <TSecond> > > (comparer); return(first .Select((f, i) => GetEnumerable(f, second[i], store, firstKeySelector, secondKeySelector, resultSelector)) .ToList()); }
internal override IList <IEnumerable <KeyValuePair <long, TResult> > > GetOrderedEnumerables(QueryOptions options) { var first = Parent.GetOrderedEnumerables(options); var second = Second.GetOrderedEnumerables(options); if (first.Count != second.Count) { throw new InvalidOperationException("Internal size mismatch"); } var store = new TemporaryArea <TKey, Tuple <VSlot <KeyValuePair <long, TFirst> >, VSlot <KeyValuePair <long, TSecond> > > > (comparer); return(first .Select((f, i) => GetEnumerable <KeyValuePair <long, TFirst>, KeyValuePair <long, TSecond>, KeyValuePair <long, TResult> > (f, second[i], store, (e) => firstKeySelector(e.Value), (e) => secondKeySelector(e.Value), (e1, e2) => new KeyValuePair <long, TResult> (e1.Key, resultSelector(e1.Value, e2.Value)))) .ToList()); }