public IEnumerable <Range <TValue> > Exclude(Range <TValue> other) { var current = this; if (current.IsEmpty || other.IsFull) { yield return(Empty); yield break; } if (other.IsEmpty) { yield return(this); yield break; } if (current.IsFull) { foreach (var r in other.Invert()) { yield return(r); } yield break; } var currentStart = current.StartValue; var currentEnd = current.EndValue; var otherStart = other.StartValue; var otherEnd = other.EndValue; var overlap = currentStart <= otherEnd && otherStart <= currentEnd; if (!overlap) { yield return(current); // Nothing to exclude } var compareStart = currentStart.CompareTo(otherStart); if (compareStart <= 0) // currentStart <= otherStart { // =====---C--------- // // --------O-- // // --------O---- // // --------O--------- // if (compareStart == 0) { if (!otherStart.Included && currentStart.Included) { var singleValueRange = new Range <TValue>(currentStart, currentStart, true, true); yield return(singleValueRange); } } else { var newRange = new Range <TValue>(currentStart, otherStart, currentStart.Included, !otherStart.Included); yield return(newRange); } } var compareEnd = currentEnd.CompareTo(otherEnd); if (compareEnd >= 0) // currentEnd >= otherEnd { // --------C----===== // // --------O------- // // --------O------------ // if (compareEnd == 0) { if (!otherEnd.Included && currentEnd.Included) { var singleValueRange = new Range <TValue>(currentEnd, currentEnd, true, true); yield return(singleValueRange); } } else { var newRange = new Range <TValue>(otherEnd, currentEnd, !otherEnd.Included, currentEnd.Included); yield return(newRange); } } }