#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