#if (NET20) using System.Collections; using System.Collections.Generic; namespace System.Linq { /// Provides a set of static (Shared in Visual Basic) methods for querying objects that implement . internal static class Enumerable { /// Determines whether any element of a sequence satisfies a condition. /// The type of the elements of . /// An whose elements to apply the predicate to. /// A function to test each element for a condition. /// true if any elements in the source sequence pass the test in the specified predicate; otherwise, false. public static bool Any(this IEnumerable source, Func predicate) { if (source == null) throw new ArgumentNullException(nameof(source)); if (predicate == null) throw new ArgumentNullException(nameof(predicate)); foreach (TSource element in source) if (predicate(element)) return true; return false; } /// Casts the elements of an to the specified type. /// The type to cast the elements of source to. /// The that contains the elements to be cast to type . /// An that contains each element of the source sequence cast to the specified type. public static IEnumerable Cast(this IEnumerable source) { foreach (var i in source) yield return (TResult)i; } /// Determines whether a sequence contains a specified element by using the default equality comparer. /// The type of the elements of . /// A sequence in which to locate a value. /// The value to locate in the sequence. /// true if the source sequence contains an element that has the specified value; otherwise, false. public static bool Contains(this IEnumerable source, TSource value) { foreach (var i in source) if (i.Equals(value)) return true; return false; } /// Returns the number of elements in a sequence. /// The type of the elements of . /// A sequence that contains elements to be counted. /// The number of elements in the input sequence. public static int Count(this IEnumerable source) { if (source == null) throw new ArgumentNullException(nameof(source)); if (source is ICollection c) return c.Count; if (source is ICollection ngc) return ngc.Count; var i = 0; foreach (var e in source) i++; return i; } /// Returns distinct elements from a sequence by using the default equality comparer to compare values. /// The type of the elements of . /// The sequence to remove duplicate elements from. /// An that contains distinct elements from the source sequence. public static IEnumerable Distinct(this IEnumerable source) { var set = new Hashtable(); foreach (var element in source) if (!set.ContainsKey(element)) { set.Add(element, null); yield return element; } } /// Returns the first element of a sequence. /// The type of the elements of . /// The to return the first element of. /// The first element in the specified sequence. public static TSource First(this IEnumerable source) { if (source == null) throw new ArgumentNullException(nameof(source)); if (source is IList list) { if (list.Count > 0) return list[0]; } else { using (var e = source.GetEnumerator()) { if (e.MoveNext()) return e.Current; } } throw new InvalidOperationException(@"No elements"); } /// Returns the first element of a sequence that satisfies a specified condition. /// The type of the elements of . /// The to return the first element of. /// A function to test each element for a condition. /// The first element in the sequence that passes the test in the specified predicate function. public static TSource First(this IEnumerable source, Func predicate) { if (source == null) throw new ArgumentNullException(nameof(source)); if (predicate == null) throw new ArgumentNullException(nameof(predicate)); foreach (var element in source) if (predicate(element)) return element; throw new InvalidOperationException(@"No match"); } /// Returns the first element of a sequence, or a default value if the sequence contains no elements. /// The type of the elements of . /// The to return the first element of. /// default( ) if is empty; otherwise, the first element in . public static TSource FirstOrDefault(this IEnumerable source) { if (source == null) throw new ArgumentNullException(nameof(source)); if (source is IList list) { if (list.Count > 0) return list[0]; } else { using (var e = source.GetEnumerator()) { if (e.MoveNext()) return e.Current; } } return default(TSource); } /// Returns the first element of the sequence that satisfies a condition or a default value if no such element is found. /// The type of the elements of source. /// An to return an element from. /// A function to test each element for a condition. /// default() if is empty or if no element passes the test specified by ; otherwise, the first element in that passes the test specified by . public static TSource FirstOrDefault(this IEnumerable source, Func predicate) { if (source == null) throw new ArgumentNullException(nameof(source)); if (predicate == null) throw new ArgumentNullException(nameof(predicate)); foreach (var element in source) if (predicate(element)) return element; return default(TSource); } /// Returns the minimum value in a generic sequence. /// The type of the elements of source. /// A sequence of values to determine the minimum value of. /// The minimum value in the sequence. public static TSource Min(this IEnumerable source) { if (source == null) throw new ArgumentNullException(nameof(source)); var comparer = Comparer.Default; var value = default(TSource); if (value == null) { foreach (var x in source) { if (x != null && (value == null || comparer.Compare(x, value) < 0)) value = x; } return value; } var hasValue = false; foreach (var x in source) { if (hasValue) { if (comparer.Compare(x, value) < 0) value = x; } else { value = x; hasValue = true; } } if (hasValue) return value; throw new InvalidOperationException("No elements"); } /// Returns the maximum value in a generic sequence. /// The type of the elements of source. /// A sequence of values to determine the maximum value of. /// The maximum value in the sequence. public static TSource Max(this IEnumerable source) { if (source == null) throw new ArgumentNullException(nameof(source)); var comparer = Comparer.Default; var value = default(TSource); if (value == null) { foreach (var x in source) { if (x != null && (value == null || comparer.Compare(x, value) > 0)) value = x; } return value; } var hasValue = false; foreach (var x in source) { if (hasValue) { if (comparer.Compare(x, value) > 0) value = x; } else { value = x; hasValue = true; } } if (hasValue) return value; throw new InvalidOperationException("No elements"); } /// Sorts the elements of a sequence in ascending order according to a key. /// The type of the elements of . /// The type of the key returned by . /// A sequence of values to order. /// A function to extract a key from an element. /// An whose elements are sorted according to a key. public static IEnumerable OrderBy(this IEnumerable source, Func keySelector) { var d = new SortedDictionary(); foreach (var item in source) d.Add(keySelector(item), item); return d.Values; } /// Projects each element of a sequence into a new form. /// The type of the elements of . /// The type of the value returned by . /// A sequence of values to invoke a transform function on. /// A transform function to apply to each element. /// An whose elements are the result of invoking the transform function on each element of . public static IEnumerable Select(this IEnumerable source, Func selector) { if (selector == null) throw new ArgumentNullException(nameof(selector)); foreach (var i in source) yield return selector(i); } /// Returns the only element of a sequence that satisfies a specified condition, and throws an exception if more than one such element exists. /// The type of the elements of . /// An to return a single element from. /// A function to test an element for a condition. /// The single element of the input sequence that satisfies a condition. public static TSource Single(this IEnumerable source, Func predicate) { if (source == null) throw new ArgumentNullException(nameof(source)); if (predicate == null) throw new ArgumentNullException(nameof(predicate)); var result = default(TSource); long count = 0; foreach (var element in source) { if (!predicate(element)) continue; result = element; checked { count++; } } if (count == 0) throw new InvalidOperationException(@"No matches"); if (count != 1) throw new InvalidOperationException(@"More than one match."); return result; } /// Computes the sum of a sequence of nullable values. /// A sequence of nullable values to calculate the sum of. /// The sum of the values in the sequence. public static int Sum(this IEnumerable source) { if (source == null) throw new ArgumentNullException(nameof(source)); int sum = 0; checked { foreach (int v in source) sum += v; } return sum; } /// /// Computes the sum of the sequence of nullable values that are obtained by invoking a transform function on each element of the input sequence. /// /// The type of the elements of . /// A sequence of values that are used to calculate a sum. /// A transform function to apply to each element. /// The sum of the projected values. public static int Sum(this IEnumerable source, Func selector) => Sum(Select(source, selector)); /// Creates an array from a . /// The type of the elements of . /// An to create an array from. /// An array that contains the elements from the input sequence. public static TSource[] ToArray(this IEnumerable source) => ToList(source).ToArray(); /// /// Creates a from an according to a specified key selector function, a comparer, and /// an element selector function. /// /// The type of the elements of . /// The type of the key returned by . /// The type of the value returned by . /// An to create a from. /// A function to extract a key from each element. /// A transform function to produce a result element value from each element. /// An to compare keys. /// A that contains values of type TElement selected from the input sequence. public static Dictionary ToDictionary(this IEnumerable source, Func keySelector, Func elementSelector, IEqualityComparer comparer) { if (source == null) throw new ArgumentNullException(nameof(source)); if (keySelector == null) throw new ArgumentNullException(nameof(keySelector)); if (elementSelector == null) throw new ArgumentNullException(nameof(elementSelector)); var d = new Dictionary(comparer); foreach (var element in source) d.Add(keySelector(element), elementSelector(element)); return d; } /// Creates a from an . /// The type of the elements of . /// An to create a from. /// A that contains elements from the input sequence. public static List ToList(this IEnumerable source) { var l = new List(); foreach (var i in source) l.Add(i); return l; } /// Filters a sequence of values based on a predicate. /// The type of the elements of . /// An to filter. /// A function to test each element for a condition. /// An that contains elements from the input sequence that satisfy the condition. public static IEnumerable Where(this IEnumerable source, Func predicate) { if (predicate == null) throw new ArgumentNullException(nameof(predicate)); foreach (var i in source) if (predicate(i)) yield return i; } } } #endif