public int GetHashCode(Wrapper<T> x) { Debug.Assert(_comparer != null); return _comparer.GetHashCode(x.Value); }
//--------------------------------------------------------------------------------------- // Walks the two data sources, left and then right, to produce the intersection. // internal override bool MoveNext(ref TInputOutput currentElement, ref TLeftKey currentKey) { Debug.Assert(_leftSource != null); Debug.Assert(_rightSource != null); // Build the set out of the left data source, if we haven't already. int i = 0; if (_hashLookup == null) { _hashLookup = new Dictionary <Wrapper <TInputOutput>, Pair>(_comparer); Pair leftElement = new Pair(default(TInputOutput), default(NoKeyMemoizationRequired)); TLeftKey leftKey = default(TLeftKey); while (_leftSource.MoveNext(ref leftElement, ref leftKey)) { if ((i++ & CancellationState.POLL_INTERVAL) == 0) { CancellationState.ThrowIfCanceled(_cancellationToken); } // For each element, we track the smallest order key for that element that we saw so far Pair oldEntry; Wrapper <TInputOutput> wrappedLeftElem = new Wrapper <TInputOutput>((TInputOutput)leftElement.First); // If this is the first occurrence of this element, or the order key is lower than all keys we saw previously, // update the order key for this element. if (!_hashLookup.TryGetValue(wrappedLeftElem, out oldEntry) || _leftKeyComparer.Compare(leftKey, (TLeftKey)oldEntry.Second) < 0) { // For each "elem" value, we store the smallest key, and the element value that had that key. // Note that even though two element values are "equal" according to the EqualityComparer, // we still cannot choose arbitrarily which of the two to yield. _hashLookup[wrappedLeftElem] = new Pair(leftElement.First, leftKey); } } } // Now iterate over the right data source, looking for matches. Pair rightElement = new Pair(default(TInputOutput), default(NoKeyMemoizationRequired)); int rightKeyUnused = default(int); while (_rightSource.MoveNext(ref rightElement, ref rightKeyUnused)) { if ((i++ & CancellationState.POLL_INTERVAL) == 0) { CancellationState.ThrowIfCanceled(_cancellationToken); } // If we found the element in our set, and if we haven't returned it yet, // we can yield it to the caller. We also mark it so we know we've returned // it once already and never will again. Pair entry; Wrapper <TInputOutput> wrappedRightElem = new Wrapper <TInputOutput>((TInputOutput)rightElement.First); if (_hashLookup.TryGetValue(wrappedRightElem, out entry)) { currentElement = (TInputOutput)entry.First; currentKey = (TLeftKey)entry.Second; _hashLookup.Remove(new Wrapper <TInputOutput>((TInputOutput)entry.First)); return(true); } } return(false); }
public bool Equals(Wrapper<T> x, Wrapper<T> y) { Debug.Assert(_comparer != null); return _comparer.Equals(x.Value, y.Value); }