Esempio n. 1
0
        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();
                }
            }
        }
Esempio n. 2
0
        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);
            }
        }