コード例 #1
0
        public static int?Max(this IEnumerable <int?> source)
        {
            if (source == null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source);
            }

            int?value = null;

            using (IEnumerator <int?> e = source.GetEnumerator())
            {
                do
                {
                    if (!e.MoveNext())
                    {
                        return(value);
                    }

                    value = e.Current;
                }while (!value.HasValue);

                int valueVal = value.GetValueOrDefault();
                if (valueVal >= 0)
                {
                    // We can fast-path this case where we know HasValue will
                    // never affect the outcome, without constantly checking
                    // if we're in such a state. Similar fast-paths could
                    // be done for other cases, but as all-positive
                    // or mostly-positive integer values are quite common in real-world
                    // uses, it's only been done in this direction for int? and long?.
                    while (e.MoveNext())
                    {
                        int?cur = e.Current;
                        int x   = cur.GetValueOrDefault();
                        if (x > valueVal)
                        {
                            valueVal = x;
                            value    = cur;
                        }
                    }
                }
                else
                {
                    while (e.MoveNext())
                    {
                        int?cur = e.Current;
                        int x   = cur.GetValueOrDefault();

                        // Do not replace & with &&. The branch prediction cost outweighs the extra operation
                        // unless nulls either never happen or always happen.
                        if (cur.HasValue & x > valueVal)
                        {
                            valueVal = x;
                            value    = cur;
                        }
                    }
                }
            }

            return(value);
        }
コード例 #2
0
ファイル: Min.cs プロジェクト: ilanb1996/runtime
        public static TSource?Min <TSource>(this IEnumerable <TSource> source, IComparer <TSource>?comparer)
        {
            if (source == null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source);
            }

            comparer ??= Comparer <TSource> .Default;

            TSource?value = default;

            using (IEnumerator <TSource> e = source.GetEnumerator())
            {
                if (value == null)
                {
                    do
                    {
                        if (!e.MoveNext())
                        {
                            return(value);
                        }

                        value = e.Current;
                    }while (value == null);

                    while (e.MoveNext())
                    {
                        TSource next = e.Current;
                        if (next != null && comparer.Compare(next, value) < 0)
                        {
                            value = next;
                        }
                    }
                }
                else
                {
                    if (!e.MoveNext())
                    {
                        ThrowHelper.ThrowNoElementsException();
                    }

                    value = e.Current;
                    if (comparer == Comparer <TSource> .Default)
                    {
                        while (e.MoveNext())
                        {
                            TSource next = e.Current;
                            if (Comparer <TSource> .Default.Compare(next, value) < 0)
                            {
                                value = next;
                            }
                        }
                    }
                    else
                    {
                        while (e.MoveNext())
                        {
                            TSource next = e.Current;
                            if (comparer.Compare(next, value) < 0)
                            {
                                value = next;
                            }
                        }
                    }
                }
            }

            return(value);
        }
コード例 #3
0
        public static TSource?MaxBy <TSource, TKey>(this IEnumerable <TSource> source, Func <TSource, TKey> keySelector, IComparer <TKey>?comparer)
        {
            if (source == null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source);
            }

            if (keySelector == null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.keySelector);
            }

            comparer ??= Comparer <TKey> .Default;

            TKey?   key   = default;
            TSource?value = default;

            using (IEnumerator <TSource> e = source.GetEnumerator())
            {
                if (key == null)
                {
                    do
                    {
                        if (!e.MoveNext())
                        {
                            return(value);
                        }

                        value = e.Current;
                        key   = keySelector(value);
                    }while (key == null);

                    while (e.MoveNext())
                    {
                        TSource nextValue = e.Current;
                        TKey    nextKey   = keySelector(nextValue);
                        if (nextKey != null && comparer.Compare(nextKey, key) > 0)
                        {
                            key   = nextKey;
                            value = nextValue;
                        }
                    }
                }
                else
                {
                    if (!e.MoveNext())
                    {
                        ThrowHelper.ThrowNoElementsException();
                    }

                    value = e.Current;
                    key   = keySelector(value);
                    if (comparer == Comparer <TSource> .Default)
                    {
                        while (e.MoveNext())
                        {
                            TSource nextValue = e.Current;
                            TKey    nextKey   = keySelector(nextValue);
                            if (Comparer <TKey> .Default.Compare(nextKey, key) > 0)
                            {
                                key   = nextKey;
                                value = nextValue;
                            }
                        }
                    }
                    else
                    {
                        while (e.MoveNext())
                        {
                            TSource nextValue = e.Current;
                            TKey    nextKey   = keySelector(nextValue);
                            if (comparer.Compare(nextKey, key) > 0)
                            {
                                key   = nextKey;
                                value = nextValue;
                            }
                        }
                    }
                }
            }

            return(value);
        }
コード例 #4
0
ファイル: Max.cs プロジェクト: Vettvangur/DotnetRuntime
        public static TResult?Max <TSource, TResult>(this IEnumerable <TSource> source, Func <TSource, TResult> selector)
        {
            if (source == null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source);
            }

            if (selector == null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.selector);
            }

            Comparer <TResult> comparer = Comparer <TResult> .Default;
            TResult?           value    = default;

            if (value == null)
            {
                using (IEnumerator <TSource> e = source.GetEnumerator())
                {
                    do
                    {
                        if (!e.MoveNext())
                        {
                            return(value);
                        }

                        value = selector(e.Current);
                    }while (value == null);

                    while (e.MoveNext())
                    {
                        TResult x = selector(e.Current);
                        if (x != null && comparer.Compare(x, value) > 0)
                        {
                            value = x;
                        }
                    }
                }
            }
            else
            {
                using (IEnumerator <TSource> e = source.GetEnumerator())
                {
                    if (!e.MoveNext())
                    {
                        ThrowHelper.ThrowNoElementsException();
                    }

                    value = selector(e.Current);
                    while (e.MoveNext())
                    {
                        TResult x = selector(e.Current);
                        if (comparer.Compare(x, value) > 0)
                        {
                            value = x;
                        }
                    }
                }
            }

            return(value);
        }
コード例 #5
0
        public static bool SequenceEqual <TSource>(this IEnumerable <TSource> first, IEnumerable <TSource> second, IEqualityComparer <TSource>?comparer)
        {
            if (first == null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.first);
            }

            if (second == null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.second);
            }

            if (comparer == null)
            {
                // It's relatively common to see code (especially in tests and testing frameworks) that ends up
                // using Enumerable.SequenceEqual to compare two byte arrays.  Using ReadOnlySpan.SequenceEqual
                // is significantly faster than accessing each byte via the array's IList<byte> interface
                // implementation.  So, we special-case byte[] here.  It would be nice to be able to delegate
                // to ReadOnlySpan.SequenceEqual for all TSource[] arrays where TSource is a value type and
                // implements IEquatable<TSource>, but there's no good way without reflection to convince
                // the C# compiler to let us delegate, as ReadOnlySpan.SequenceEqual requires an IEquatable<T>
                // constraint on its type parameter, and Enumerable.SequenceEqual lacks one on its type parameter.
                if (typeof(TSource) == typeof(byte) && first is byte[] firstArr && second is byte[] secondArr)
                {
                    return(((ReadOnlySpan <byte>)firstArr).SequenceEqual(secondArr));
                }

                comparer = EqualityComparer <TSource> .Default;
            }

            if (first is ICollection <TSource> firstCol && second is ICollection <TSource> secondCol)
            {
                if (firstCol.Count != secondCol.Count)
                {
                    return(false);
                }

                if (firstCol is IList <TSource> firstList && secondCol is IList <TSource> secondList)
                {
                    int count = firstCol.Count;
                    for (int i = 0; i < count; i++)
                    {
                        if (!comparer.Equals(firstList[i], secondList[i]))
                        {
                            return(false);
                        }
                    }

                    return(true);
                }
            }

            using (IEnumerator <TSource> e1 = first.GetEnumerator())
                using (IEnumerator <TSource> e2 = second.GetEnumerator())
                {
                    while (e1.MoveNext())
                    {
                        if (!(e2.MoveNext() && comparer.Equals(e1.Current, e2.Current)))
                        {
                            return(false);
                        }
                    }

                    return(!e2.MoveNext());
                }
        }