public void Reset() { // Calling reset on an iterator throws NotSupportedException. var x = EnumerableUtility.Yield(42, 43, 45, 47, 49).ToList(); var y = EnumerableUtility.Yield(55, 56, 57, 58).ToList(); using (var enumeratorPair = new EnumeratorPair <int>(x, y)) { for (int run = 0; run < 3; run++) { for (int i = 0; i < 4; i++) { int lengthComparison; Assert.IsTrue(enumeratorPair.MoveNext()); Assert.AreEqual(x.ElementAt(i), enumeratorPair.Current1); Assert.AreEqual(y.ElementAt(i), enumeratorPair.Current2); ExceptionAssert.Throws <InvalidOperationException>(() => lengthComparison = enumeratorPair.LengthComparison); } Assert.IsFalse(enumeratorPair.MoveNext()); Assert.AreEqual(1, Math.Sign(enumeratorPair.LengthComparison)); enumeratorPair.Reset(); } } }
public void MoveNext() { var x = Enumerable.Empty <int>(); var y = Enumerable.Empty <int>(); int lengthComparison; using (var enumeratorPair = new EnumeratorPair <int>(x, y)) { Assert.IsFalse(enumeratorPair.MoveNext()); Assert.AreEqual(0, enumeratorPair.LengthComparison); } x = Enumerable.Empty <int>(); y = EnumerableUtility.Yield(42); using (var enumeratorPair = new EnumeratorPair <int>(x, y)) { Assert.IsFalse(enumeratorPair.MoveNext()); Assert.AreEqual(42, enumeratorPair.Current2); Assert.AreEqual(-1, Math.Sign(enumeratorPair.LengthComparison)); } x = EnumerableUtility.Yield(42); y = Enumerable.Empty <int>(); using (var enumeratorPair = new EnumeratorPair <int>(x, y)) { Assert.IsFalse(enumeratorPair.MoveNext()); Assert.AreEqual(42, enumeratorPair.Current1); Assert.AreEqual(1, Math.Sign(enumeratorPair.LengthComparison)); } x = EnumerableUtility.Yield(42); y = EnumerableUtility.Yield(55); using (var enumeratorPair = new EnumeratorPair <int>(x, y)) { Assert.IsTrue(enumeratorPair.MoveNext()); Assert.AreEqual(42, enumeratorPair.Current1); Assert.AreEqual(55, enumeratorPair.Current2); Assert.AreEqual(42, enumeratorPair.Current.Element1); Assert.AreEqual(55, enumeratorPair.Current.Element2); ExceptionAssert.Throws <InvalidOperationException>(() => lengthComparison = enumeratorPair.LengthComparison); Assert.IsFalse(enumeratorPair.MoveNext()); Assert.AreEqual(0, enumeratorPair.LengthComparison); } x = EnumerableUtility.Yield(42, 43, 45, 47, 49); y = EnumerableUtility.Yield(55, 56, 57, 58); using (var enumeratorPair = new EnumeratorPair <int>(x, y)) { for (int i = 0; i < 4; i++) { Assert.IsTrue(enumeratorPair.MoveNext()); Assert.AreEqual(x.ElementAt(i), enumeratorPair.Current1); Assert.AreEqual(y.ElementAt(i), enumeratorPair.Current2); Assert.AreEqual(x.ElementAt(i), enumeratorPair.Current.Element1); Assert.AreEqual(y.ElementAt(i), enumeratorPair.Current.Element2); ExceptionAssert.Throws <InvalidOperationException>(() => lengthComparison = enumeratorPair.LengthComparison); } Assert.IsFalse(enumeratorPair.MoveNext()); Assert.AreEqual(1, Math.Sign(enumeratorPair.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) { if (x.TryFastCount(out int xCount) && y.TryFastCount(out int 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. // https://referencesource.microsoft.com/#System.Core/System/Linq/Enumerable.cs,9bdd6ef7ba6a5615 // Create an enumerator pair to iterate over both sequences in sync. using (var enumeratorPair = new EnumeratorPair <TElement>(x, y)) { // Advance both enumerators to their next element, // until at least one passes the end of its sequence. while (enumeratorPair.MoveNext()) { // Compare the current pair of elements across the two sequences, // seeking element inequality. int elementComparison = _elementComparer.Compare(enumeratorPair.Current1, enumeratorPair.Current2); 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, ignoring the elements, // until at least one passes the end of its sequence. while (enumeratorPair.MoveNext()) { ; } // If one sequence was shorter than the other, then use the length comparison result. // Such logic is implemented beyond the outer while loop. if (enumeratorPair.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 length of the sequences dominates the result. // If the current sequence comparison is SameLength, // then throw exception for sequences of different lengths. if (_comparisonType == SequenceComparison.SameLength && enumeratorPair.LengthComparison != 0) { throw new ArgumentException("The sequences to be compared do not have the same number of elements."); } // Return the length comparison result. return(enumeratorPair.LengthComparison); } }