/// <summary> Yields all elements that are between the elements in the specified sorted sequence. So basically, this is exclusion of the sequence from the range of the sequence. </summary> /// <typeparam name="T"> The type of the elements. </typeparam> /// <param name="sequence"> The sequence of the elements that are not yielded. </param> /// <param name="increment"> A function specifying the next element given one. </param> /// <param name="start"> The start of the range of all elements to yield. </param> /// <param name="end"> The end of the range of all elements to yield. </param> /// <param name="equalityComparer"> The equality comparer used for determining whether an element in the specified sequence matches that in the range. </param> public static IEnumerable <T> RangeExcept <T>(this ISortedEnumerable <T> sequence, Func <T, T> increment, T start, T end, IEqualityComparer <T> equalityComparer = null) { Contract.Requires(sequence != null); Contract.Requires(increment != null); Contract.Requires(sequence.IsSorted(sequence.Comparer)); equalityComparer = equalityComparer ?? EqualityComparer <T> .Default; T previouslyExcludedElement = start; bool first = true; foreach (var excludedElement in sequence.Concat(end)) { foreach (var elementBelowExcludedElement in Range(previouslyExcludedElement, increment, excludedElement, equalityComparer, first)) { if (equalityComparer.Equals(end, elementBelowExcludedElement)) { yield break; } yield return(elementBelowExcludedElement); } if (equalityComparer.Equals(end, excludedElement)) { yield break; } previouslyExcludedElement = excludedElement; first = false; } }