/System.Core/System.Linq/Enumerable.cs
C# | 1405 lines | 1098 code | 269 blank | 38 comment | 92 complexity | cf4c6f600d17d38f2b5a875686cb3782 MD5 | raw file
- // Copyright (c) 2009 DotNetAnywhere
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to deal
- // in the Software without restriction, including without limitation the rights
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- // copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- // THE SOFTWARE.
-
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Collections;
-
- namespace System.Linq {
- public static class Enumerable {
-
- private static class Funcs<T> {
- public static readonly Func<T, bool> True = x => true;
- public static readonly Func<T, T> Identity = x => x;
- }
-
- #region Aggregate
-
- public static T Aggregate<T>(this IEnumerable<T> source, Func<T, T, T> func) {
- Check(source, func);
- using (var en = source.GetEnumerator()) {
- if (!en.MoveNext()) {
- throw new InvalidOperationException();
- }
- T value = en.Current;
- while (en.MoveNext()) {
- value = func(value, en.Current);
- }
- return value;
- }
- }
-
- public static TAcc Aggregate<T, TAcc>(this IEnumerable<T> source, TAcc seed, Func<TAcc, T, TAcc> func) {
- return source.Aggregate(seed, func, Funcs<TAcc>.Identity);
- }
-
- public static TResult Aggregate<T, TAcc, TResult>
- (this IEnumerable<T> source, TAcc seed, Func<TAcc, T, TAcc> func, Func<TAcc,TResult> resultSelector) {
- Check(source, func, resultSelector);
- foreach (var item in source) {
- seed = func(seed, item);
- }
- return resultSelector(seed);
- }
-
- #endregion
-
- #region All
-
- public static bool All<T>(this IEnumerable<T> source, Func<T, bool> predicate) {
- Check(source);
- foreach (T item in source) {
- if (!predicate(item)) {
- return false;
- }
- }
- return true;
- }
-
- #endregion
-
- #region Any
-
- public static bool Any<T>(this IEnumerable<T> source) {
- return source.Any(Funcs<T>.True);
- }
-
- public static bool Any<T>(this IEnumerable<T> source, Func<T, bool> predicate) {
- Check(source, predicate);
- foreach (T item in source) {
- if (predicate(item)) {
- return true;
- }
- }
- return false;
- }
-
- #endregion
-
- #region Average
-
- public static double Average(this IEnumerable<int> source) {
- return Avg<int, long, double>(source, (a, v) => a + v, (a, c) => (double)a / (double)c);
- }
-
- public static double? Average(this IEnumerable<int?> source) {
- return AvgNullable<int, long, double>(source, (a, v) => a + v, (a, c) => (double)a / (double)c);
- }
-
- public static double Average(this IEnumerable<long> source) {
- return Avg<long, long, double>(source, (a, v) => a + v, (a, c) => (double)a / (double)c);
- }
-
- public static double? Average(this IEnumerable<long?> source) {
- return AvgNullable<long, long, double>(source, (a, v) => a + v, (a, c) => (double)a / (double)c);
- }
-
- public static float Average(this IEnumerable<float> source) {
- return Avg<float, float, float>(source, (a, v) => a + v, (a, c) => a / c);
- }
-
- public static float? Average(this IEnumerable<float?> source) {
- return AvgNullable<float, float, float>(source, (a, v) => a + v, (a, c) => a / c);
- }
-
- public static double Average(this IEnumerable<double> source) {
- return Avg<double, double, double>(source, (a, v) => a + v, (a, c) => a / c);
- }
-
- public static double? Average(this IEnumerable<double?> source) {
- return AvgNullable<double, double, double>(source, (a, v) => a + v, (a, c) => a / c);
- }
-
- public static Decimal Average(this IEnumerable<Decimal> source) {
- throw new NotImplementedException();
- }
-
- public static Decimal? Average(this IEnumerable<Decimal?> source) {
- throw new NotImplementedException();
- }
-
- public static double Average<T>(this IEnumerable<T> source, Func<T, int> selector) {
- return Avg<int, long, double>(source.Select(selector), (a, v) => a + v, (a, c) => (double)a / (double)c);
- }
-
- public static double? Average<T>(this IEnumerable<T> source, Func<T, int?> selector) {
- return AvgNullable<int, long, double>(source.Select(selector), (a, v) => a + v, (a, c) => (double)a / (double)c);
- }
-
- public static double Average<T>(this IEnumerable<T> source, Func<T, long> selector) {
- return Avg<long, long, double>(source.Select(selector), (a, v) => a + v, (a, c) => (double)a / (double)c);
- }
-
- public static double? Average<T>(this IEnumerable<T> source, Func<T, long?> selector) {
- return AvgNullable<long, long, double>(source.Select(selector), (a, v) => a + v, (a, c) => (double)a / (double)c);
- }
-
- public static float Average<T>(this IEnumerable<T> source, Func<T, float> selector) {
- return Avg<float, float, float>(source.Select(selector), (a, v) => a + v, (a, c) => a / c);
- }
-
- public static float? Average<T>(this IEnumerable<T> source, Func<T, float?> selector) {
- return AvgNullable<float, float, float>(source.Select(selector), (a, v) => a + v, (a, c) => a / c);
- }
-
- public static double Average<T>(this IEnumerable<T> source, Func<T, double> selector) {
- return Avg<double, double, double>(source.Select(selector), (a, v) => a + v, (a, c) => a / c);
- }
-
- public static double? Average<T>(this IEnumerable<T> source, Func<T, double?> selector) {
- return AvgNullable<double, double, double>(source.Select(selector), (a, v) => a + v, (a, c) => a / c);
- }
-
- public static Decimal Average<T>(this IEnumerable<T> source, Func<T, Decimal> selector) {
- throw new NotImplementedException();
- }
-
- public static Decimal? Average<T>(this IEnumerable<T> source, Func<T, Decimal?> selector) {
- throw new NotImplementedException();
- }
-
- private static TRes Avg<T, TAcc, TRes>(IEnumerable<T> source,
- Func<TAcc, T, TAcc> accFn, Func<TAcc, int, TRes> resFn) {
- Check(source);
- TAcc acc = default(TAcc);
- int counter = 0;
- foreach (var item in source) {
- acc = accFn(acc, item);
- counter++;
- }
- if (counter == 0) {
- throw new InvalidOperationException();
- }
- return resFn(acc, counter);
- }
-
- private static TRes? AvgNullable<T, TAcc, TRes>(IEnumerable<T?> source,
- Func<TAcc, T, TAcc> accFn, Func<TAcc, int, TRes> resFn)
- where T : struct
- where TRes : struct {
- Check(source);
- TAcc acc = default(TAcc);
- int counter = 0;
- foreach (var item in source) {
- if (item != null) {
- acc = accFn(acc, item.Value);
- counter++;
- }
- }
- if (counter == 0) {
- return null;
- }
- return resFn(acc, counter);
- }
-
- #endregion
-
- #region AsEnumerable
-
- public static IEnumerable<T> AsEnumerable<T>(this IEnumerable<T> source) {
- return source;
- }
-
- #endregion
-
- #region Cast
-
- public static IEnumerable<T> Cast<T>(IEnumerable source) {
- Check(source);
- return CastIterator<T>(source);
- }
-
- private static IEnumerable<T> CastIterator<T>(IEnumerable source) {
- foreach (T item in source) {
- yield return item;
- }
- }
-
- #endregion
-
- #region Concat
-
- public static IEnumerable<T> Concat<T>
- (this IEnumerable<T> first, IEnumerable<T> second) {
- Check(first, second);
- return ConcatIterator(first, second);
- }
-
- private static IEnumerable<T> ConcatIterator<T>
- (IEnumerable<T> first, IEnumerable<T> second) {
- foreach (T item in first) {
- yield return item;
- }
- foreach (T item in second) {
- yield return item;
- }
- }
-
- #endregion
-
- #region Contains
-
- public static bool Contains<T>(this IEnumerable<T> source, T value) {
- return source.Contains(value, null);
- }
-
- public static bool Contains<T>
- (this IEnumerable<T> source, T value, IEqualityComparer<T> comparer) {
- Check(source);
- if (comparer == null) {
- comparer = EqualityComparer<T>.Default;
- }
- foreach (T item in source) {
- if (comparer.Equals(item, value)) {
- return true;
- }
- }
- return false;
- }
-
- #endregion
-
- #region Count, LongCount
-
- public static int Count<T>(this IEnumerable<T> source) {
- Check(source);
- ICollection<T> collection = source as ICollection<T>;
- if (collection != null) {
- return collection.Count;
- } else {
- return source.Count(Funcs<T>.True);
- }
- }
-
- public static int Count<T>(this IEnumerable<T> source, Func<T, bool> predicate) {
- Check(source, predicate);
- int count = 0;
- foreach (T item in source) {
- if (predicate(item)) {
- count++;
- }
- }
- return count;
- }
-
- public static long LongCount<T>(this IEnumerable<T> source) {
- return (long)Count(source);
- }
-
- public static long LongCount<T>(this IEnumerable<T> source, Func<T, bool> predicate) {
- return (long)Count(source, predicate);
- }
-
- #endregion
-
- #region DefaultIfEmpty
-
- public static IEnumerable<T> DefaultIfEmpty<T>(this IEnumerable<T> source) {
- return source.DefaultIfEmpty(default(T));
- }
-
- public static IEnumerable<T> DefaultIfEmpty<T>(this IEnumerable<T> source, T defaultValue) {
- Check(source);
- return DefaultIfEmptyIterator(source, defaultValue);
- }
-
- private static IEnumerable<T> DefaultIfEmptyIterator<T>(IEnumerable<T> source, T defaultValue) {
- using (IEnumerator<T> en = source.GetEnumerator()) {
- if (en.MoveNext()) {
- do {
- yield return en.Current;
- } while (en.MoveNext());
- } else {
- yield return defaultValue;
- }
- }
- }
-
- #endregion
-
- #region Distinct
-
- public static IEnumerable<T> Distinct<T>(this IEnumerable<T> source) {
- return Distinct(source, null);
- }
-
- public static IEnumerable<T> Distinct<T>(this IEnumerable<T> source, IEqualityComparer<T> comparer) {
- return DistinctIterator(source, comparer);
- }
-
- private static IEnumerable<T> DistinctIterator<T>(IEnumerable<T> source, IEqualityComparer<T> comparer) {
- HashSet<T> h = new HashSet<T>(comparer);
- foreach (T item in source) {
- if (h.Add(item)) {
- yield return item;
- }
- }
- }
-
- #endregion
-
- #region ElementAt, ElementAtOrDefault
-
- public static T ElementAt<T>(IEnumerable<T> source, int index) {
- return ElementAt(source, index, false);
- }
-
- public static T ElementAtOrDefault<T>(IEnumerable<T> source, int index) {
- return ElementAt(source, index, true);
- }
-
- private static T ElementAt<T>(IEnumerable<T> source, int index, bool orDefault) {
- Check(source);
- if (index >= 0) {
- IList<T> list = source as IList<T>;
- if (list != null) {
- if (index < list.Count) {
- return list[index];
- }
- } else {
- int count = 0;
- foreach (T item in source) {
- if (count == index) {
- return item;
- }
- count++;
- }
- }
- }
- if (orDefault) {
- return default(T);
- } else {
- throw new ArgumentOutOfRangeException();
- }
- }
-
- #endregion
-
- #region Empty
-
- public static IEnumerable<T> Empty<T>() {
- return new T[0];
- }
-
- #endregion
-
- #region Except
-
- public static IEnumerable<T> Except<T>(this IEnumerable<T> first, IEnumerable<T> second) {
- return Except(first, second, null);
- }
-
- public static IEnumerable<T> Except<T>
- (this IEnumerable<T> first, IEnumerable<T> second, IEqualityComparer<T> comparer) {
- Check(first, second);
- return ExceptIterator(first, second, comparer);
- }
-
- private static IEnumerable<T> ExceptIterator<T>
- (IEnumerable<T> first, IEnumerable<T> second, IEqualityComparer<T> comparer) {
- HashSet<T> h = new HashSet<T>(second, comparer);
- foreach (T item in first) {
- if (!h.Contains(item)) {
- yield return item;
- }
- }
- }
-
- #endregion
-
- #region First, FirstOrDefault, Single, SingleOrDefault
-
- private static T FirstSingle<T>(IEnumerable<T> source, Func<T, bool> predicate, bool single, bool retDefault) {
- Check(source, predicate);
- using (var en = source.Where(predicate).GetEnumerator()) {
- if (en.MoveNext()) {
- T value = en.Current;
- if (single) {
- if (en.MoveNext()) {
- throw new InvalidOperationException();
- }
- }
- return value;
- } else {
- if (retDefault) {
- return default(T);
- } else {
- throw new InvalidOperationException();
- }
- }
- }
- }
-
- public static T First<T>(this IEnumerable<T> source) {
- return FirstSingle(source, Funcs<T>.True, false, false);
- }
-
- public static T First<T>(this IEnumerable<T> source, Func<T, bool> predicate) {
- return FirstSingle(source, predicate, false, false);
- }
-
- public static T FirstOrDefault<T>(this IEnumerable<T> source) {
- return FirstSingle(source, Funcs<T>.True, false, true);
- }
-
- public static T FirstOrDefault<T>(this IEnumerable<T> source, Func<T, bool> predicate) {
- return FirstSingle(source, predicate, false, true);
- }
-
- public static T Single<T>(this IEnumerable<T> source) {
- return FirstSingle(source, Funcs<T>.True, true, false);
- }
-
- public static T Single<T>(this IEnumerable<T> source, Func<T, bool> predicate) {
- return FirstSingle(source, predicate, true, false);
- }
-
- public static T SingleOrDefault<T>(this IEnumerable<T> source) {
- return FirstSingle(source, Funcs<T>.True, true, true);
- }
-
- public static T SingleOrDefault<T>(this IEnumerable<T> source, Func<T, bool> predicate) {
- return FirstSingle(source, predicate, true, true);
- }
-
- #endregion
-
- #region GroupBy
-
- public static IEnumerable<IGrouping<TKey, TSource>> GroupBy<TSource, TKey>
- (this IEnumerable<TSource> source, Func<TSource, TKey> keySelector) {
- return source.GroupBy(keySelector, null);
- }
-
- public static IEnumerable<IGrouping<TKey, TSource>> GroupBy<TSource, TKey>
- (this IEnumerable<TSource> source, Func<TSource, TKey> keySelector,
- IEqualityComparer<TKey> comparer) {
- return source.GroupBy(keySelector, Funcs<TSource>.Identity, comparer);
- }
-
- public static IEnumerable<IGrouping<TKey, TElement>> GroupBy<TSource, TKey, TElement>
- (this IEnumerable<TSource> source, Func<TSource, TKey> keySelector,
- Func<TSource, TElement> elementSelector) {
- return source.GroupBy(keySelector, elementSelector, null);
- }
-
- public static IEnumerable<IGrouping<TKey, TElement>> GroupBy<TSource, TKey, TElement>
- (this IEnumerable<TSource> source, Func<TSource, TKey> keySelector,
- Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer) {
- return source.GroupBy(keySelector, elementSelector,
- (key, elements) => (IGrouping<TKey, TElement>)new Grouping<TKey, TElement>(key, elements),
- comparer);
- }
-
- public static IEnumerable<TResult> GroupBy<TSource, TKey, TResult>
- (this IEnumerable<TSource> source, Func<TSource, TKey> keySelector,
- Func<TKey, IEnumerable<TSource>, TResult> resultSelector) {
- return source.GroupBy(keySelector, resultSelector, null);
- }
-
- public static IEnumerable<TResult> GroupBy<TSource, TKey, TResult>
- (this IEnumerable<TSource> source, Func<TSource, TKey> keySelector,
- Func<TKey, IEnumerable<TSource>, TResult> resultSelector, IEqualityComparer<TKey> comparer) {
- return source.GroupBy(keySelector, Funcs<TSource>.Identity, resultSelector, comparer);
- }
-
- public static IEnumerable<TResult> GroupBy<TSource, TKey, TElement, TResult>
- (this IEnumerable<TSource> source, Func<TSource, TKey> keySelector,
- Func<TSource, TElement> elementSelector, Func<TKey, IEnumerable<TElement>, TResult> resultSelector) {
- return source.GroupBy(keySelector, elementSelector, resultSelector, null);
- }
-
- public static IEnumerable<TResult> GroupBy<TSource, TKey, TElement, TResult>
- (this IEnumerable<TSource> source, Func<TSource, TKey> keySelector,
- Func<TSource, TElement> elementSelector, Func<TKey, IEnumerable<TElement>, TResult> resultSelector,
- IEqualityComparer<TKey> comparer) {
- Check(source, keySelector, elementSelector);
- Check(resultSelector);
- return GroupByIterator(source, keySelector, elementSelector, resultSelector, comparer);
- }
-
- private static IEnumerable<TResult> GroupByIterator<TSource, TKey, TElement, TResult>
- (IEnumerable<TSource> source, Func<TSource, TKey> keySelector,
- Func<TSource, TElement> elementSelector, Func<TKey, IEnumerable<TElement>, TResult> resultSelector,
- IEqualityComparer<TKey> comparer) {
- Dictionary<TKey, List<TElement>> groups = new Dictionary<TKey, List<TElement>>(comparer);
- foreach (var item in source) {
- TKey key = keySelector(item);
- TElement element = elementSelector(item);
- List<TElement> itemsInGroup;
- if (!groups.TryGetValue(key, out itemsInGroup)) {
- itemsInGroup = new List<TElement>();
- groups.Add(key, itemsInGroup);
- }
- itemsInGroup.Add(element);
- }
- foreach (var group in groups) {
- yield return resultSelector(group.Key, group.Value);
- }
- }
-
- #endregion
-
- #region GroupJoin
-
- public static IEnumerable<TResult> GroupJoin<TOuter, TInner, TKey, TResult>
- (this IEnumerable<TOuter> outer, IEnumerable<TInner> inner,
- Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector,
- Func<TOuter, IEnumerable<TInner>, TResult> resultSelector) {
- return outer.GroupJoin(inner, outerKeySelector, innerKeySelector, resultSelector, null);
- }
-
- public static IEnumerable<TResult> GroupJoin<TOuter, TInner, TKey, TResult>
- (this IEnumerable<TOuter> outer, IEnumerable<TInner> inner,
- Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector,
- Func<TOuter, IEnumerable<TInner>, TResult> resultSelector,
- IEqualityComparer<TKey> comparer) {
- Check(outer, inner, outerKeySelector);
- Check(innerKeySelector, resultSelector);
- return GroupJoinIterator(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer);
- }
-
- public static IEnumerable<TResult> GroupJoinIterator<TOuter, TInner, TKey, TResult>
- (IEnumerable<TOuter> outer, IEnumerable<TInner> inner,
- Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector,
- Func<TOuter, IEnumerable<TInner>, TResult> resultSelector,
- IEqualityComparer<TKey> comparer) {
- var innerLookup = inner.ToLookup(innerKeySelector, comparer);
- foreach (var outerItem in outer) {
- TKey outerKey = outerKeySelector(outerItem);
- yield return resultSelector(outerItem,
- innerLookup.Contains(outerKey) ? innerLookup[outerKey] : Empty<TInner>());
- }
- }
- #endregion
-
- #region Intersect
-
- public static IEnumerable<T> Intersect<T>(this IEnumerable<T> first, IEnumerable<T> second) {
- return first.Intersect(second, null);
- }
-
- public static IEnumerable<T> Intersect<T>(this IEnumerable<T> first, IEnumerable<T> second,
- IEqualityComparer<T> comparer) {
- Check(first, second);
- return IntersectIterator(first, second, comparer);
- }
-
- private static IEnumerable<T> IntersectIterator<T>(IEnumerable<T> first, IEnumerable<T> second,
- IEqualityComparer<T> comparer) {
- HashSet<T> hash = new HashSet<T>(first, comparer);
- foreach (var item in second.Distinct(comparer)) {
- if (hash.Contains(item)) {
- yield return item;
- }
- }
- }
-
- #endregion
-
- #region Join
-
- public static IEnumerable<TResult> Join<TOuter, TInner, TKey, TResult>
- (this IEnumerable<TOuter> outer, IEnumerable<TInner> inner,
- Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector,
- Func<TOuter, TInner, TResult> resultSelector) {
- return outer.Join(inner, outerKeySelector, innerKeySelector, resultSelector, null);
- }
-
- public static IEnumerable<TResult> Join<TOuter, TInner, TKey, TResult>
- (this IEnumerable<TOuter> outer, IEnumerable<TInner> inner,
- Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector,
- Func<TOuter, TInner, TResult> resultSelector, IEqualityComparer<TKey> comparer) {
- Check(outer, inner);
- Check(outerKeySelector, innerKeySelector, resultSelector);
- return JoinIterator(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer);
- }
-
- private static IEnumerable<TResult> JoinIterator<TOuter, TInner, TKey, TResult>
- (IEnumerable<TOuter> outer, IEnumerable<TInner> inner,
- Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector,
- Func<TOuter, TInner, TResult> resultSelector, IEqualityComparer<TKey> comparer) {
- var outerLookup = outer.ToLookup(outerKeySelector, comparer);
- foreach (TInner innerItem in inner) {
- TKey innerKey = innerKeySelector(innerItem);
- if (outerLookup.Contains(innerKey)) {
- foreach (TOuter outerItem in outerLookup[innerKey]) {
- yield return resultSelector(outerItem, innerItem);
- }
- }
- }
- }
-
- #endregion
-
- #region Last, LastOrDefault
-
- private static T LastOrDefault<T>(IEnumerable<T> source, Func<T, bool> predicate, bool retDefault) {
- Check(source, predicate);
- T last = default(T);
- bool empty = true;
- foreach (T item in source) {
- if (predicate(item)) {
- empty = false;
- last = item;
- }
- }
- if (empty && !retDefault) {
- throw new InvalidOperationException();
- }
- return last;
- }
-
- public static T Last<T>(this IEnumerable<T> source) {
- return LastOrDefault(source, Funcs<T>.True, false);
- }
-
- public static T Last<T>(this IEnumerable<T> source, Func<T, bool> predicate) {
- return LastOrDefault(source, predicate, false);
- }
-
- public static T LastOrDefault<T>(this IEnumerable<T> source) {
- return LastOrDefault(source, Funcs<T>.True, true);
- }
-
- public static T LastOrDefault<T>(this IEnumerable<T> source, Func<T, bool> predicate) {
- return LastOrDefault(source, predicate, true);
- }
-
- #endregion
-
- #region Max
-
- public static int Max(this IEnumerable<int> source) {
- return GenProc(source, (a, b) => Math.Max(a, b), false);
- }
-
- public static int? Max(this IEnumerable<int?> source) {
- return GenProcNullable(source, (a, b) => Math.Max(a, b));
- }
-
- public static long Max(this IEnumerable<long> source) {
- return GenProc(source, (a, b) => Math.Max(a, b), false);
- }
-
- public static long? Max(this IEnumerable<long?> source) {
- return GenProcNullable(source, (a, b) => Math.Max(a, b));
- }
-
- public static float Max(this IEnumerable<float> source) {
- return GenProc(source, (a, b) => Math.Max(a, b), false);
- }
-
- public static float? Max(this IEnumerable<float?> source) {
- return GenProcNullable(source, (a, b) => Math.Max(a, b));
- }
-
- public static double Max(this IEnumerable<double> source) {
- return GenProc(source, (a, b) => Math.Max(a, b), false);
- }
-
- public static double? Max(this IEnumerable<double?> source) {
- return GenProcNullable(source, (a, b) => Math.Max(a, b));
- }
-
- public static Decimal Max(this IEnumerable<Decimal> source) {
- throw new NotImplementedException();
- }
-
- public static Decimal? Max(this IEnumerable<Decimal?> source) {
- throw new NotImplementedException();
- }
-
- public static T Max<T>(this IEnumerable<T> source) {
- Comparer<T> comparer = Comparer<T>.Default;
- return GenProc(source, (a, b) => comparer.Compare(a, b) > 0 ? a : b, true);
- }
-
- public static TResult Max<T, TResult>(this IEnumerable<T> source, Func<T, TResult> selector) {
- return Max(source.Select(selector));
- }
-
- public static int Max<T>(this IEnumerable<T> source, Func<T, int> selector) {
- return Max(source.Select(selector));
- }
-
- public static int? Max<T>(this IEnumerable<T> source, Func<T, int?> selector) {
- return Max(source.Select(selector));
- }
-
- public static long Max<T>(this IEnumerable<T> source, Func<T, long> selector) {
- return Max(source.Select(selector));
- }
-
- public static long? Max<T>(this IEnumerable<T> source, Func<T, long?> selector) {
- return Max(source.Select(selector));
- }
-
- public static float Max<T>(this IEnumerable<T> source, Func<T, float> selector) {
- return Max(source.Select(selector));
- }
-
- public static float? Max<T>(this IEnumerable<T> source, Func<T, float?> selector) {
- return Max(source.Select(selector));
- }
-
- public static double Max<T>(this IEnumerable<T> source, Func<T, double> selector) {
- return Max(source.Select(selector));
- }
-
- public static double? Max<T>(this IEnumerable<T> source, Func<T, double?> selector) {
- return Max(source.Select(selector));
- }
-
- public static Decimal Max<T>(this IEnumerable<T> source, Func<T, Decimal> selector) {
- return Max(source.Select(selector));
- }
-
- public static Decimal? Max<T>(this IEnumerable<T> source, Func<T, Decimal?> selector) {
- return Max(source.Select(selector));
- }
-
- #endregion
-
- #region Min
-
- public static int Min(this IEnumerable<int> source) {
- return GenProc(source, (a, b) => Math.Min(a, b), false);
- }
-
- public static int? Min(this IEnumerable<int?> source) {
- return GenProcNullable(source, (a, b) => Math.Min(a, b));
- }
-
- public static long Min(this IEnumerable<long> source) {
- return GenProc(source, (a, b) => Math.Min(a, b), false);
- }
-
- public static long? Min(this IEnumerable<long?> source) {
- return GenProcNullable(source, (a, b) => Math.Min(a, b));
- }
-
- public static float Min(this IEnumerable<float> source) {
- return GenProc(source, (a, b) => Math.Min(a, b), false);
- }
-
- public static float? Min(this IEnumerable<float?> source) {
- return GenProcNullable(source, (a, b) => Math.Min(a, b));
- }
-
- public static double Min(this IEnumerable<double> source) {
- return GenProc(source, (a, b) => Math.Min(a, b), false);
- }
-
- public static double? Min(this IEnumerable<double?> source) {
- return GenProcNullable(source, (a, b) => Math.Min(a, b));
- }
-
- public static Decimal Min(this IEnumerable<Decimal> source) {
- throw new NotImplementedException();
- }
-
- public static Decimal? Min(this IEnumerable<Decimal?> source) {
- throw new NotImplementedException();
- }
-
- public static T Min<T>(this IEnumerable<T> source) {
- Comparer<T> comparer = Comparer<T>.Default;
- return GenProc(source, (a, b) => comparer.Compare(a, b) < 0 ? a : b, true);
- }
-
- public static TResult Min<T, TResult>(this IEnumerable<T> source, Func<T, TResult> selector) {
- return Min(source.Select(selector));
- }
-
- public static int Min<T>(this IEnumerable<T> source, Func<T, int> selector) {
- return Min(source.Select(selector));
- }
-
- public static int? Min<T>(this IEnumerable<T> source, Func<T, int?> selector) {
- return Min(source.Select(selector));
- }
-
- public static long Min<T>(this IEnumerable<T> source, Func<T, long> selector) {
- return Min(source.Select(selector));
- }
-
- public static long? Min<T>(this IEnumerable<T> source, Func<T, long?> selector) {
- return Min(source.Select(selector));
- }
-
- public static float Min<T>(this IEnumerable<T> source, Func<T, float> selector) {
- return Min(source.Select(selector));
- }
-
- public static float? Min<T>(this IEnumerable<T> source, Func<T, float?> selector) {
- return Min(source.Select(selector));
- }
-
- public static double Min<T>(this IEnumerable<T> source, Func<T, double> selector) {
- return Min(source.Select(selector));
- }
-
- public static double? Min<T>(this IEnumerable<T> source, Func<T, double?> selector) {
- return Min(source.Select(selector));
- }
-
- public static Decimal Min<T>(this IEnumerable<T> source, Func<T, Decimal> selector) {
- return Min(source.Select(selector));
- }
-
- public static Decimal? Min<T>(this IEnumerable<T> source, Func<T, Decimal?> selector) {
- return Min(source.Select(selector));
- }
-
- private static T GenProc<T>(IEnumerable<T> source, Func<T, T, T> fn, bool allowEmpty) {
- Check(source);
- using (var en = source.GetEnumerator()) {
- if (!en.MoveNext()) {
- if (allowEmpty) {
- return default(T);
- } else {
- throw new InvalidOperationException();
- }
- }
- T value = en.Current;
- while (en.MoveNext()) {
- value = fn(value, en.Current);
- }
- return value;
- }
- }
-
- private static T? GenProcNullable<T>(IEnumerable<T?> source, Func<T, T, T> fn) where T : struct {
- T? value = null;
- foreach (T? item in source) {
- if (value == null) {
- value = item;
- } else if (item != null) {
- value = fn(value.Value, item.Value);
- }
- }
- return value;
- }
-
- #endregion
-
- #region OfType
-
- public static IEnumerable<T> OfType<T>(this IEnumerable source) {
- Check(source);
- return OfTypeIterator<T>(source);
- }
-
- private static IEnumerable<T> OfTypeIterator<T>(IEnumerable source) {
- foreach (object item in source) {
- if (item is T) {
- yield return (T)item;
- }
- }
- }
-
- #endregion
-
- #region OrderBy, OrderByDescending
-
- public static IOrderedEnumerable<T> OrderBy<T, TKey>(
- this IEnumerable<T> source,
- Func<T, TKey> selector,
- IComparer<TKey> comparer) {
- Check(source, selector);
- return new OrderedEnumerable<T, TKey>(source, selector, comparer, true);
- }
-
- public static IOrderedEnumerable<T> OrderBy<T, TKey>(
- this IEnumerable<T> source,
- Func<T, TKey> selector) {
- Check(source, selector);
- return new OrderedEnumerable<T, TKey>(source, selector, null, true);
- }
-
- public static IOrderedEnumerable<T> OrderByDescending<T, TKey>(
- this IEnumerable<T> source,
- Func<T, TKey> selector,
- IComparer<TKey> comparer) {
- Check(source, selector);
- return new OrderedEnumerable<T, TKey>(source, selector, comparer, false);
- }
-
- public static IOrderedEnumerable<T> OrderByDescending<T, TKey>(
- this IEnumerable<T> source,
- Func<T, TKey> selector) {
- Check(source, selector);
- return new OrderedEnumerable<T, TKey>(source, selector, null, false);
- }
-
- #endregion
-
- #region Range
-
- public static IEnumerable<int> Range(int start, int count) {
- if (count < 0) {
- throw new ArgumentOutOfRangeException("count");
- }
- return RangeIterator(start, count);
- }
-
- private static IEnumerable<int> RangeIterator(int start, int count) {
- int end = start + count;
- for (int i = start; i < end; i++) {
- yield return i;
- }
- }
-
- #endregion
-
- #region Repeat
-
- public static IEnumerable<TResult> Repeat<TResult>(TResult element, int count) {
- if (count < 0) {
- throw new ArgumentOutOfRangeException("count");
- }
- return RepeatIterator(element, count);
- }
-
- private static IEnumerable<TResult> RepeatIterator<TResult>(TResult element, int count) {
- for (int i = 0; i < count; i++) {
- yield return element;
- }
- }
-
- #endregion
-
- #region Reverse
-
- public static IEnumerable<T> Reverse<T>(this IEnumerable<T> source) {
- Check(source);
- IList<T> list = source as IList<T> ?? new List<T>(source);
- return ReverseIterator(list);
- }
-
- private static IEnumerable<T> ReverseIterator<T>(IList<T> source) {
- for (int i = source.Count - 1; i >= 0; i--) {
- yield return source[i];
- }
- }
-
- #endregion
-
- #region Select
-
- public static IEnumerable<TResult> Select<T, TResult>
- (this IEnumerable<T> source, Func<T, TResult> selector) {
- Check(source, selector);
- return SelectIterator(source, selector);
- }
-
- private static IEnumerable<TResult> SelectIterator<T, TResult>
- (IEnumerable<T> source, Func<T, TResult> selector) {
- foreach (T item in source) {
- yield return selector(item);
- }
- }
-
- public static IEnumerable<TResult> Select<T, TResult>
- (this IEnumerable<T> source, Func<T, int, TResult> selector) {
- Check(source, selector);
- return SelectIterator(source, selector);
- }
-
- private static IEnumerable<TResult> SelectIterator<T, TResult>
- (IEnumerable<T> source, Func<T, int, TResult> selector) {
- int count = 0;
- foreach (T item in source) {
- yield return selector(item, count);
- count++;
- }
- }
-
- #endregion
-
- #region SelectMany
-
- public static IEnumerable<TResult> SelectMany<TSource, TResult>
- (this IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> selector) {
- return source.SelectMany((s, i) => selector(s));
- }
-
- public static IEnumerable<TResult> SelectMany<TSource, TResult>
- (this IEnumerable<TSource> source, Func<TSource, int, IEnumerable<TResult>> selector) {
- return source.SelectMany(selector, (s, c) => c);
- }
-
- public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult>
- (this IEnumerable<TSource> source, Func<TSource, IEnumerable<TCollection>> collectionSelector,
- Func<TSource, TCollection, TResult> resultSelector) {
- return source.SelectMany((s, i) => collectionSelector(s), resultSelector);
- }
-
- public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult>
- (this IEnumerable<TSource> source, Func<TSource, int, IEnumerable<TCollection>> collectionSelector,
- Func<TSource, TCollection, TResult> resultSelector) {
- Check(source, collectionSelector, resultSelector);
- return SelectManyIterator(source, collectionSelector, resultSelector);
- }
-
- private static IEnumerable<TResult> SelectManyIterator<TSource, TCollection, TResult>
- (IEnumerable<TSource> source, Func<TSource, int, IEnumerable<TCollection>> collectionSelector,
- Func<TSource, TCollection, TResult> resultSelector) {
- int count = 0;
- foreach (TSource item in source) {
- foreach (TCollection col in collectionSelector(item, count)) {
- yield return resultSelector(item, col);
- }
- count++;
- }
- }
-
- #endregion
-
- #region SequenceEqual
-
- public static bool SequenceEqual<T>(this IEnumerable<T> first, IEnumerable<T> second) {
- return first.SequenceEqual(second, null);
- }
-
- public static bool SequenceEqual<T>(this IEnumerable<T> first, IEnumerable<T> second, IEqualityComparer<T> comparer) {
- Check(first, second);
- if (comparer == null) {
- comparer = EqualityComparer<T>.Default;
- }
- using (IEnumerator<T> en1 = first.GetEnumerator(), en2 = second.GetEnumerator()) {
- while (en1.MoveNext()) {
- if (!en2.MoveNext()) {
- return false;
- }
- if (!comparer.Equals(en1.Current, en2.Current)) {
- return false;
- }
- }
- return !en2.MoveNext();
- }
- }
-
- #endregion
-
- #region Skip
-
- public static IEnumerable<T> Skip<T>(this IEnumerable<T> source, int count) {
- Check(source);
- return SkipIterator(source, count);
- }
-
- private static IEnumerable<T> SkipIterator<T>(IEnumerable<T> source, int count) {
- foreach (T item in source) {
- if (count <= 0) {
- yield return item;
- }
- count--;
- }
- }
-
- #endregion
-
- #region SkipWhile
-
- public static IEnumerable<T> SkipWhile<T>(this IEnumerable<T> source, Func<T, bool> predicate) {
- Check(source, predicate);
- return SkipWhileIterator(source, predicate);
- }
-
- public static IEnumerable<T> SkipWhileIterator<T>(IEnumerable<T> source, Func<T, bool> predicate) {
- bool skip = true;
- foreach (T item in source) {
- if (skip) {
- if (!predicate(item)) {
- skip = false;
- yield return item;
- }
- } else {
- yield return item;
- }
- }
- }
-
- public static IEnumerable<T> SkipWhile<T>(this IEnumerable<T> source, Func<T, int, bool> predicate) {
- Check(source, predicate);
- return SkipWhileIterator(source, predicate);
- }
-
- public static IEnumerable<T> SkipWhileIterator<T>(IEnumerable<T> source, Func<T, int, bool> predicate) {
- bool skip = true;
- int count = 0;
- foreach (T item in source) {
- if (skip) {
- if (!predicate(item, count)) {
- skip = false;
- yield return item;
- }
- } else {
- yield return item;
- }
- count++;
- }
- }
-
- #endregion
-
- #region Take
-
- public static IEnumerable<T> Take<T>(this IEnumerable<T> source, int count) {
- Check(source);
- return TakeIterator(source, count);
- }
-
- private static IEnumerable<T> TakeIterator<T>(IEnumerable<T> source, int count) {
- if (count <= 0) {
- yield break;
- }
- foreach (T item in source) {
- yield return item;
- count--;
- if (count == 0) {
- yield break;
- }
- }
- }
-
- #endregion
-
- #region TakeWhile
-
- public static IEnumerable<T> TakeWhile<T>(this IEnumerable<T> source, Func<T, bool> predicate) {
- Check(source, predicate);
- return TakeWhileIterator(source, predicate);
- }
-
- private static IEnumerable<T> TakeWhileIterator<T>(IEnumerable<T> source, Func<T, bool> predicate) {
- foreach (T item in source) {
- if (!predicate(item)) {
- yield break;
- }
- yield return item;
- }
- }
-
- public static IEnumerable<T> TakeWhile<T>(this IEnumerable<T> source, Func<T, int, bool> predicate) {
- Check(source, predicate);
- return TakeWhileIterator(source, predicate);
- }
-
- private static IEnumerable<T> TakeWhileIterator<T>(IEnumerable<T> source, Func<T, int, bool> predicate) {
- int count = 0;
- foreach (T item in source) {
- if (!predicate(item, count)) {
- yield break;
- }
- yield return item;
- count++;
- }
- }
-
- #endregion
-
- #region ThenBy, ThenByDescending
-
- //public static IOrderedEnumerable<T> ThenBy<T, TKey>(this IOrderedEnumerable<T> source,
- // Func<T, TKey> keySelector) {
- // return source.ThenBy(keySelector, null);
- //}
-
- //public static IOrderedEnumerable<T> ThenBy<T, TKey>(this IOrderedEnumerable<T> source,
- // Func<T, TKey> keySelector, IComparer<TKey> comparer) {
- // Check(source, keySelector);
- // return source.CreateOrderedEnumerable(keySelector, comparer, false);
- //}
-
- //public static IOrderedEnumerable<T> ThenByDescending<T, TKey>(this IOrderedEnumerable<T> source,
- // Func<T, TKey> keySelector) {
- // return source.ThenByDescending(keySelector, null);
- //}
-
- //public static IOrderedEnumerable<T> ThenByDescending<T, TKey>(this IOrderedEnumerable<T> source,
- // Func<T, TKey> keySelector, IComparer<TKey> comparer) {
- // Check(source, keySelector);
- // return source.CreateOrderedEnumerable(keySelector, comparer, true);
- //}
-
- #endregion
-
- #region Union
-
- public static IEnumerable<T> Union<T>(this IEnumerable<T> first, IEnumerable<T> second) {
- return Union(first, second, null);
- }
-
- public static IEnumerable<T> Union<T>
- (this IEnumerable<T> first, IEnumerable<T> second, IEqualityComparer<T> comparer) {
- // Check not needed, as Concat() will do it
- return DistinctIterator(first.Concat(second), comparer);
- }
-
- #endregion
-
- #region Where
-
- public static IEnumerable<T> Where<T>
- (this IEnumerable<T> source, Func<T, bool> predicate) {
- Check(source, predicate);
- return WhereIterator(source, predicate);
- }
-
- private static IEnumerable<T> WhereIterator<T>
- (IEnumerable<T> source, Func<T, bool> predicate) {
- foreach (T item in source) {
- if (predicate(item)) {
- yield return item;
- }
- }
- }
-
- public static IEnumerable<T> Where<T>
- (this IEnumerable<T> source, Func<T, int, bool> predicate) {
- Check(source, predicate);
- return WhereIterator(source, predicate);
- }
-
- private static IEnumerable<T> WhereIterator<T>
- (IEnumerable<T> source, Func<T, int, bool> predicate) {
- int count = 0;
- foreach (T item in source) {
- if (predicate(item, count)) {
- yield return item;
- }
- count++;
- }
- }
-
- #endregion
-
- #region ToList, ToArray, ToDictionary, ToLookup
-
- public static List<T> ToList<T>(this IEnumerable<T> source) {
- Check(source);
- return new List<T>(source);
- }
-
- public static T[] ToArray<T>(this IEnumerable<T> source) {
- Check(source);
- ICollection<T> collection =
- source as ICollection<T> ?? new List<T>(source);
- T[] result = new T[collection.Count];
- collection.CopyTo(result, 0);
- return result;
- }
-
- public static Dictionary<TKey, TSource> ToDictionary<TSource, TKey>(
- this IEnumerable<TSource> source, Func<TSource, TKey> keySelector) {
- return source.ToDictionary(keySelector, Funcs<TSource>.Identity, null);
- }
-
- public static Dictionary<TKey, TSource> ToDictionary<TSource, TKey>(
- this IEnumerable<TSource> source, Func<TSource, TKey> keySelector,
- IEqualityComparer<TKey> comparer) {
- return source.ToDictionary(keySelector, Funcs<TSource>.Identity, comparer);
- }
-
- public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement>(
- this IEnumerable<TSource> source, Func<TSource, TKey> keySelector,
- Func<TSource, TElement> elementSelector) {
- return source.ToDictionary(keySelector, elementSelector, null);
- }
-
- public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement>(
- this IEnumerable<TSource> source, Func<TSource, TKey> keySelector,
- Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer) {
- Check(source, keySelector, elementSelector);
- Dictionary<TKey, TElement> dict = new Dictionary<TKey, TElement>(comparer);
- foreach (TSource item in source) {
- dict.Add(keySelector(item), elementSelector(item));
- }
- return dict;
- }
-
- public static ILookup<TKey, TSource> ToLookup<TSource, TKey>(
- this IEnumerable<TSource> source, Func<TSource, TKey> keySelector) {
- return source.ToLookup(keySelector, Funcs<TSource>.Identity, null);
- }
-
- public static ILookup<TKey, TSource> ToLookup<TSource, TKey>(
- this IEnumerable<TSource> source, Func<TSource, TKey> keySelector,
- IEqualityComparer<TKey> comparer) {
- return source.ToLookup(keySelector, Funcs<TSource>.Identity, comparer);
- }
-
- public static ILookup<TKey, TElement> ToLookup<TSource, TKey, TElement>(
- this IEnumerable<TSource> source, Func<TSource, TKey> keySelector,
- Func<TSource, TElement> elementSelector) {
- return source.ToLookup(keySelector, elementSelector, null);
- }
-
- public static ILookup<TKey, TElement> ToLookup<TSource, TKey, TElement>(
- this IEnumerable<TSource> source, Func<TSource, TKey> keySelector,
- Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer) {
- Check(source, keySelector, elementSelector);
- var lookup = new Dictionary<TKey, List<TElement>>(comparer);
- foreach (TSource item in source) {
- TKey key = keySelector(item);
- if (key == null) {
- throw new ArgumentNullException();
- }
- List<TElement> list;
- if (!lookup.TryGetValue(key, out list)) {
- list = new List<TElement>();
- lookup.Add(key, list);
- }
- list.Add(elementSelector(item));
- }
- return new Lookup<TKey, TElement>(lookup);
- }
-
- #endregion
-
- #region Checks
-
- private static void Check(object o) {
- if (o == null) {
- throw new ArgumentNullException();
- }
- }
-
- private static void Check(object o1, object o2) {
- if (o1 == null || o2 == null) {
- throw new ArgumentNullException();
- }
- }
-
- private static void Check(object o1, object o2, object o3) {
- if (o1 == null || o2 == null || o3 == null) {
- throw new ArgumentNullException();
- }
- }
-
- #endregion
-
- }
- }