Exemple #1
0
        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);
                }
        }