public void MoveNextBoth() { int lengthComparison; using (var x = Enumerable.Empty <int>().GetEnumerator()) using (var y = Enumerable.Empty <int>().GetEnumerator()) { Assert.IsFalse(EnumeratorUtility.MoveNextBoth(x, y, out lengthComparison)); Assert.AreEqual(0, lengthComparison); } using (var x = Enumerable.Empty <int>().GetEnumerator()) using (var y = EnumerableUtility.Yield(42).GetEnumerator()) { Assert.IsFalse(EnumeratorUtility.MoveNextBoth(x, y, out lengthComparison)); Assert.AreEqual(-1, Math.Sign(lengthComparison)); } using (var x = EnumerableUtility.Yield(42).GetEnumerator()) using (var y = Enumerable.Empty <int>().GetEnumerator()) { Assert.IsFalse(EnumeratorUtility.MoveNextBoth(x, y, out lengthComparison)); Assert.AreEqual(1, Math.Sign(lengthComparison)); } using (var x = EnumerableUtility.Yield(42).GetEnumerator()) using (var y = EnumerableUtility.Yield(55).GetEnumerator()) { Assert.IsTrue(EnumeratorUtility.MoveNextBoth(x, y, out lengthComparison)); Assert.AreEqual(0, lengthComparison); Assert.IsFalse(EnumeratorUtility.MoveNextBoth(x, y, out lengthComparison)); Assert.AreEqual(0, lengthComparison); } using (var x = EnumerableUtility.Yield(42, 45, 48, 49).GetEnumerator()) using (var y = EnumerableUtility.Yield(55, 56, 57, 58, 59).GetEnumerator()) { for (int i = 0; i < 4; i++) { Assert.IsTrue(EnumeratorUtility.MoveNextBoth(x, y, out lengthComparison)); Assert.AreEqual(0, lengthComparison); } Assert.IsFalse(EnumeratorUtility.MoveNextBoth(x, y, out lengthComparison)); Assert.AreEqual(-1, Math.Sign(lengthComparison)); } }
/// <summary> /// Compares two sequences of elements and returns a value indicating whether one is less than, equal to, /// or greater than the other. /// </summary> /// <param name="x">The first sequence of elements to compare.</param> /// <param name="y">The second sequence of elements to compare.</param> /// <returns> /// A signed integer that indicates the relative values of <paramref name="x"/> and <paramref name="y"/>, /// as shown in the following table: /// <list type="table"> /// <listheader> /// <term>Value</term> /// <term>Meaning</term> /// </listheader> /// <item> /// <term>Less than zero</term> /// <term><paramref name="x"/> is less than <paramref name="y"/>.</term> /// </item> /// <item> /// <term>Zero</term> /// <term><paramref name="x"/> is equal to <paramref name="y"/>.</term> /// </item> /// <item> /// <term>Greater than zero</term> /// <term><paramref name="x"/> is greater than <paramref name="y"/>.</term> /// </item> /// </list> /// </returns> protected override int CompareNonNull(IEnumerable <TElement> x, IEnumerable <TElement> y) { // Optimization for in-memory collections: // If the current sequence comparison is Shortlex or SameLength, // then attempt to perform a length comparison without enumerating the sequences. if (_lengthDominated) { int xCount, yCount; if (x.TryFastCount(out xCount) && y.TryFastCount(out yCount)) { int countComparison = xCount.CompareTo(yCount); if (countComparison != 0) { // Shortlex returns immediately for sequences of different lengths, // whilst SameLength throws immediately for such sequences. if (_comparisonType == SequenceComparison.Shortlex) { return(countComparison); } if (_comparisonType == SequenceComparison.SameLength) { throw new ArgumentException("The sequences to be compared do not have the same number of elements."); } } } } // For an example of how to use enumerators, refer to the source code for the Enumerable.SequenceEqual method. // http://referencesource.microsoft.com/#System.Core/System/Linq/Enumerable.cs,9bdd6ef7ba6a5615 // Get enumerators to iterate through both sequences in sync. using (IEnumerator <TElement> xEnumerator = x.GetEnumerator()) using (IEnumerator <TElement> yEnumerator = y.GetEnumerator()) { // Advance both enumerators to their next element, until at least one passes the end of its sequence. int lengthComparison; while (EnumeratorUtility.MoveNextBoth(xEnumerator, yEnumerator, out lengthComparison)) { // Compare the current pair of elements across the two sequences, // seeking element inequality. int elementComparison = _elementComparer.Compare(xEnumerator.Current, yEnumerator.Current); if (elementComparison != 0) { // If the current sequence comparison is Shortlex or SameLength, // then length inequality needs to be given precedence over element inequality. if (_lengthDominated) { // Advance both enumerators until at least one passes the end of its sequence. while (EnumeratorUtility.MoveNextBoth(xEnumerator, yEnumerator, out lengthComparison)) { ; } // If one sequence was shorter than the other, then use the length comparison result. // Such logic is implemented after the outer while loop. if (lengthComparison != 0) { break; } } // If the current sequence comparison is Lexicographical, // or the sequences have been found to share the same length, // then return the non-zero element comparison result. return(elementComparison); } } // This point is only reached if at least one sequence ended without finding any unequal pair of elements; // or an unequal pair of elements was found, but the unequal lengths of the sequences dominates the result. // If the current sequence comparison is SameLength, // then throw exception for sequences of different lengths. if (lengthComparison != 0 && _comparisonType == SequenceComparison.SameLength) { throw new ArgumentException("The sequences to be compared do not have the same number of elements."); } // Return the length comparison result. return(lengthComparison); } }