diff --git a/src/libraries/System.Linq.Queryable/ref/System.Linq.Queryable.cs b/src/libraries/System.Linq.Queryable/ref/System.Linq.Queryable.cs index 060cf4df2dc6d..692f4bc23ac5d 100644 --- a/src/libraries/System.Linq.Queryable/ref/System.Linq.Queryable.cs +++ b/src/libraries/System.Linq.Queryable/ref/System.Linq.Queryable.cs @@ -80,7 +80,9 @@ public static partial class Queryable public static System.Linq.IQueryable Distinct(this System.Linq.IQueryable source) { throw null; } public static System.Linq.IQueryable Distinct(this System.Linq.IQueryable source, System.Collections.Generic.IEqualityComparer? comparer) { throw null; } public static TSource? ElementAtOrDefault(this System.Linq.IQueryable source, int index) { throw null; } + public static TSource? ElementAtOrDefault(this System.Linq.IQueryable source, System.Index index) { throw null; } public static TSource ElementAt(this System.Linq.IQueryable source, int index) { throw null; } + public static TSource ElementAt(this System.Linq.IQueryable source, System.Index index) { throw null; } public static System.Linq.IQueryable Except(this System.Linq.IQueryable source1, System.Collections.Generic.IEnumerable source2) { throw null; } public static System.Linq.IQueryable Except(this System.Linq.IQueryable source1, System.Collections.Generic.IEnumerable source2, System.Collections.Generic.IEqualityComparer? comparer) { throw null; } public static TSource? FirstOrDefault(this System.Linq.IQueryable source) { throw null; } @@ -158,6 +160,7 @@ public static partial class Queryable public static System.Linq.IQueryable TakeWhile(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> predicate) { throw null; } public static System.Linq.IQueryable TakeWhile(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> predicate) { throw null; } public static System.Linq.IQueryable Take(this System.Linq.IQueryable source, int count) { throw null; } + public static System.Linq.IQueryable Take(this System.Linq.IQueryable source, System.Range range) { throw null; } public static System.Linq.IOrderedQueryable ThenByDescending(this System.Linq.IOrderedQueryable source, System.Linq.Expressions.Expression> keySelector) { throw null; } public static System.Linq.IOrderedQueryable ThenByDescending(this System.Linq.IOrderedQueryable source, System.Linq.Expressions.Expression> keySelector, System.Collections.Generic.IComparer? comparer) { throw null; } public static System.Linq.IOrderedQueryable ThenBy(this System.Linq.IOrderedQueryable source, System.Linq.Expressions.Expression> keySelector) { throw null; } diff --git a/src/libraries/System.Linq.Queryable/src/System/Linq/CachedReflection.cs b/src/libraries/System.Linq.Queryable/src/System/Linq/CachedReflection.cs index f7e9a83002de3..f0eb0f169bf3c 100644 --- a/src/libraries/System.Linq.Queryable/src/System/Linq/CachedReflection.cs +++ b/src/libraries/System.Linq.Queryable/src/System/Linq/CachedReflection.cs @@ -15,878 +15,768 @@ internal static class CachedReflectionInfo private static MethodInfo? s_Aggregate_TSource_2; public static MethodInfo Aggregate_TSource_2(Type TSource) => - (s_Aggregate_TSource_2 ?? - (s_Aggregate_TSource_2 = new Func, Expression>, object>(Queryable.Aggregate).GetMethodInfo().GetGenericMethodDefinition())) + (s_Aggregate_TSource_2 ??= new Func, Expression>, object>(Queryable.Aggregate).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Aggregate_TSource_TAccumulate_3; public static MethodInfo Aggregate_TSource_TAccumulate_3(Type TSource, Type TAccumulate) => - (s_Aggregate_TSource_TAccumulate_3 ?? - (s_Aggregate_TSource_TAccumulate_3 = new Func, object, Expression>, object>(Queryable.Aggregate).GetMethodInfo().GetGenericMethodDefinition())) + (s_Aggregate_TSource_TAccumulate_3 ??= new Func, object, Expression>, object>(Queryable.Aggregate).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TAccumulate); private static MethodInfo? s_Aggregate_TSource_TAccumulate_TResult_4; public static MethodInfo Aggregate_TSource_TAccumulate_TResult_4(Type TSource, Type TAccumulate, Type TResult) => - (s_Aggregate_TSource_TAccumulate_TResult_4 ?? - (s_Aggregate_TSource_TAccumulate_TResult_4 = new Func, object, Expression>, Expression>, object>(Queryable.Aggregate).GetMethodInfo().GetGenericMethodDefinition())) + (s_Aggregate_TSource_TAccumulate_TResult_4 ??= new Func, object, Expression>, Expression>, object>(Queryable.Aggregate).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TAccumulate, TResult); private static MethodInfo? s_All_TSource_2; public static MethodInfo All_TSource_2(Type TSource) => - (s_All_TSource_2 ?? - (s_All_TSource_2 = new Func, Expression>, bool>(Queryable.All).GetMethodInfo().GetGenericMethodDefinition())) + (s_All_TSource_2 ??= new Func, Expression>, bool>(Queryable.All).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Any_TSource_1; public static MethodInfo Any_TSource_1(Type TSource) => - (s_Any_TSource_1 ?? - (s_Any_TSource_1 = new Func, bool>(Queryable.Any).GetMethodInfo().GetGenericMethodDefinition())) + (s_Any_TSource_1 ??= new Func, bool>(Queryable.Any).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Any_TSource_2; public static MethodInfo Any_TSource_2(Type TSource) => - (s_Any_TSource_2 ?? - (s_Any_TSource_2 = new Func, Expression>, bool>(Queryable.Any).GetMethodInfo().GetGenericMethodDefinition())) + (s_Any_TSource_2 ??= new Func, Expression>, bool>(Queryable.Any).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Average_Int32_1; public static MethodInfo Average_Int32_1 => - s_Average_Int32_1 ?? - (s_Average_Int32_1 = new Func, double>(Queryable.Average).GetMethodInfo()); + s_Average_Int32_1 ??= new Func, double>(Queryable.Average).GetMethodInfo(); private static MethodInfo? s_Average_NullableInt32_1; public static MethodInfo Average_NullableInt32_1 => - s_Average_NullableInt32_1 ?? - (s_Average_NullableInt32_1 = new Func, double?>(Queryable.Average).GetMethodInfo()); + s_Average_NullableInt32_1 ??= new Func, double?>(Queryable.Average).GetMethodInfo(); private static MethodInfo? s_Average_Int64_1; public static MethodInfo Average_Int64_1 => - s_Average_Int64_1 ?? - (s_Average_Int64_1 = new Func, double>(Queryable.Average).GetMethodInfo()); + s_Average_Int64_1 ??= new Func, double>(Queryable.Average).GetMethodInfo(); private static MethodInfo? s_Average_NullableInt64_1; public static MethodInfo Average_NullableInt64_1 => - s_Average_NullableInt64_1 ?? - (s_Average_NullableInt64_1 = new Func, double?>(Queryable.Average).GetMethodInfo()); + s_Average_NullableInt64_1 ??= new Func, double?>(Queryable.Average).GetMethodInfo(); private static MethodInfo? s_Average_Single_1; public static MethodInfo Average_Single_1 => - s_Average_Single_1 ?? - (s_Average_Single_1 = new Func, float>(Queryable.Average).GetMethodInfo()); + s_Average_Single_1 ??= new Func, float>(Queryable.Average).GetMethodInfo(); private static MethodInfo? s_Average_NullableSingle_1; public static MethodInfo Average_NullableSingle_1 => - s_Average_NullableSingle_1 ?? - (s_Average_NullableSingle_1 = new Func, float?>(Queryable.Average).GetMethodInfo()); + s_Average_NullableSingle_1 ??= new Func, float?>(Queryable.Average).GetMethodInfo(); private static MethodInfo? s_Average_Double_1; public static MethodInfo Average_Double_1 => - s_Average_Double_1 ?? - (s_Average_Double_1 = new Func, double>(Queryable.Average).GetMethodInfo()); + s_Average_Double_1 ??= new Func, double>(Queryable.Average).GetMethodInfo(); private static MethodInfo? s_Average_NullableDouble_1; public static MethodInfo Average_NullableDouble_1 => - s_Average_NullableDouble_1 ?? - (s_Average_NullableDouble_1 = new Func, double?>(Queryable.Average).GetMethodInfo()); + s_Average_NullableDouble_1 ??= new Func, double?>(Queryable.Average).GetMethodInfo(); private static MethodInfo? s_Average_Decimal_1; public static MethodInfo Average_Decimal_1 => - s_Average_Decimal_1 ?? - (s_Average_Decimal_1 = new Func, decimal>(Queryable.Average).GetMethodInfo()); + s_Average_Decimal_1 ??= new Func, decimal>(Queryable.Average).GetMethodInfo(); private static MethodInfo? s_Average_NullableDecimal_1; public static MethodInfo Average_NullableDecimal_1 => - s_Average_NullableDecimal_1 ?? - (s_Average_NullableDecimal_1 = new Func, decimal?>(Queryable.Average).GetMethodInfo()); + s_Average_NullableDecimal_1 ??= new Func, decimal?>(Queryable.Average).GetMethodInfo(); private static MethodInfo? s_Average_Int32_TSource_2; public static MethodInfo Average_Int32_TSource_2(Type TSource) => - (s_Average_Int32_TSource_2 ?? - (s_Average_Int32_TSource_2 = new Func, Expression>, double>(Queryable.Average).GetMethodInfo().GetGenericMethodDefinition())) + (s_Average_Int32_TSource_2 ??= new Func, Expression>, double>(Queryable.Average).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Average_NullableInt32_TSource_2; public static MethodInfo Average_NullableInt32_TSource_2(Type TSource) => - (s_Average_NullableInt32_TSource_2 ?? - (s_Average_NullableInt32_TSource_2 = new Func, Expression>, double?>(Queryable.Average).GetMethodInfo().GetGenericMethodDefinition())) + (s_Average_NullableInt32_TSource_2 ??= new Func, Expression>, double?>(Queryable.Average).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Average_Single_TSource_2; public static MethodInfo Average_Single_TSource_2(Type TSource) => - (s_Average_Single_TSource_2 ?? - (s_Average_Single_TSource_2 = new Func, Expression>, float>(Queryable.Average).GetMethodInfo().GetGenericMethodDefinition())) + (s_Average_Single_TSource_2 ??= new Func, Expression>, float>(Queryable.Average).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Average_NullableSingle_TSource_2; public static MethodInfo Average_NullableSingle_TSource_2(Type TSource) => - (s_Average_NullableSingle_TSource_2 ?? - (s_Average_NullableSingle_TSource_2 = new Func, Expression>, float?>(Queryable.Average).GetMethodInfo().GetGenericMethodDefinition())) + (s_Average_NullableSingle_TSource_2 ??= new Func, Expression>, float?>(Queryable.Average).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Average_Int64_TSource_2; public static MethodInfo Average_Int64_TSource_2(Type TSource) => - (s_Average_Int64_TSource_2 ?? - (s_Average_Int64_TSource_2 = new Func, Expression>, double>(Queryable.Average).GetMethodInfo().GetGenericMethodDefinition())) + (s_Average_Int64_TSource_2 ??= new Func, Expression>, double>(Queryable.Average).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Average_NullableInt64_TSource_2; public static MethodInfo Average_NullableInt64_TSource_2(Type TSource) => - (s_Average_NullableInt64_TSource_2 ?? - (s_Average_NullableInt64_TSource_2 = new Func, Expression>, double?>(Queryable.Average).GetMethodInfo().GetGenericMethodDefinition())) + (s_Average_NullableInt64_TSource_2 ??= new Func, Expression>, double?>(Queryable.Average).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Average_Double_TSource_2; public static MethodInfo Average_Double_TSource_2(Type TSource) => - (s_Average_Double_TSource_2 ?? - (s_Average_Double_TSource_2 = new Func, Expression>, double>(Queryable.Average).GetMethodInfo().GetGenericMethodDefinition())) + (s_Average_Double_TSource_2 ??= new Func, Expression>, double>(Queryable.Average).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Average_NullableDouble_TSource_2; public static MethodInfo Average_NullableDouble_TSource_2(Type TSource) => - (s_Average_NullableDouble_TSource_2 ?? - (s_Average_NullableDouble_TSource_2 = new Func, Expression>, double?>(Queryable.Average).GetMethodInfo().GetGenericMethodDefinition())) + (s_Average_NullableDouble_TSource_2 ??= new Func, Expression>, double?>(Queryable.Average).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Average_Decimal_TSource_2; public static MethodInfo Average_Decimal_TSource_2(Type TSource) => - (s_Average_Decimal_TSource_2 ?? - (s_Average_Decimal_TSource_2 = new Func, Expression>, decimal>(Queryable.Average).GetMethodInfo().GetGenericMethodDefinition())) + (s_Average_Decimal_TSource_2 ??= new Func, Expression>, decimal>(Queryable.Average).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Average_NullableDecimal_TSource_2; public static MethodInfo Average_NullableDecimal_TSource_2(Type TSource) => - (s_Average_NullableDecimal_TSource_2 ?? - (s_Average_NullableDecimal_TSource_2 = new Func, Expression>, decimal?>(Queryable.Average).GetMethodInfo().GetGenericMethodDefinition())) + (s_Average_NullableDecimal_TSource_2 ??= new Func, Expression>, decimal?>(Queryable.Average).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Cast_TResult_1; public static MethodInfo Cast_TResult_1(Type TResult) => - (s_Cast_TResult_1 ?? - (s_Cast_TResult_1 = new Func>(Queryable.Cast).GetMethodInfo().GetGenericMethodDefinition())) + (s_Cast_TResult_1 ??= new Func>(Queryable.Cast).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TResult); private static MethodInfo? s_Chunk_TSource_1; public static MethodInfo Chunk_TSource_1(Type TSource) => - (s_Chunk_TSource_1 ?? - (s_Chunk_TSource_1 = new Func, int, IQueryable>(Queryable.Chunk).GetMethodInfo().GetGenericMethodDefinition())) + (s_Chunk_TSource_1 ??= new Func, int, IQueryable>(Queryable.Chunk).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Concat_TSource_2; public static MethodInfo Concat_TSource_2(Type TSource) => - (s_Concat_TSource_2 ?? - (s_Concat_TSource_2 = new Func, IEnumerable, IQueryable>(Queryable.Concat).GetMethodInfo().GetGenericMethodDefinition())) + (s_Concat_TSource_2 ??= new Func, IEnumerable, IQueryable>(Queryable.Concat).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Contains_TSource_2; public static MethodInfo Contains_TSource_2(Type TSource) => - (s_Contains_TSource_2 ?? - (s_Contains_TSource_2 = new Func, object, bool>(Queryable.Contains).GetMethodInfo().GetGenericMethodDefinition())) + (s_Contains_TSource_2 ??= new Func, object, bool>(Queryable.Contains).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Contains_TSource_3; public static MethodInfo Contains_TSource_3(Type TSource) => - (s_Contains_TSource_3 ?? - (s_Contains_TSource_3 = new Func, object, IEqualityComparer, bool>(Queryable.Contains).GetMethodInfo().GetGenericMethodDefinition())) + (s_Contains_TSource_3 ??= new Func, object, IEqualityComparer, bool>(Queryable.Contains).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Count_TSource_1; public static MethodInfo Count_TSource_1(Type TSource) => - (s_Count_TSource_1 ?? - (s_Count_TSource_1 = new Func, int>(Queryable.Count).GetMethodInfo().GetGenericMethodDefinition())) + (s_Count_TSource_1 ??= new Func, int>(Queryable.Count).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Count_TSource_2; public static MethodInfo Count_TSource_2(Type TSource) => - (s_Count_TSource_2 ?? - (s_Count_TSource_2 = new Func, Expression>, int>(Queryable.Count).GetMethodInfo().GetGenericMethodDefinition())) + (s_Count_TSource_2 ??= new Func, Expression>, int>(Queryable.Count).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_DefaultIfEmpty_TSource_1; public static MethodInfo DefaultIfEmpty_TSource_1(Type TSource) => - (s_DefaultIfEmpty_TSource_1 ?? - (s_DefaultIfEmpty_TSource_1 = new Func, IQueryable>(Queryable.DefaultIfEmpty).GetMethodInfo().GetGenericMethodDefinition())) + (s_DefaultIfEmpty_TSource_1 ??= new Func, IQueryable>(Queryable.DefaultIfEmpty).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_DefaultIfEmpty_TSource_2; public static MethodInfo DefaultIfEmpty_TSource_2(Type TSource) => - (s_DefaultIfEmpty_TSource_2 ?? - (s_DefaultIfEmpty_TSource_2 = new Func, object, IQueryable>(Queryable.DefaultIfEmpty).GetMethodInfo().GetGenericMethodDefinition())) + (s_DefaultIfEmpty_TSource_2 ??= new Func, object, IQueryable>(Queryable.DefaultIfEmpty).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Distinct_TSource_1; public static MethodInfo Distinct_TSource_1(Type TSource) => - (s_Distinct_TSource_1 ?? - (s_Distinct_TSource_1 = new Func, IQueryable>(Queryable.Distinct).GetMethodInfo().GetGenericMethodDefinition())) + (s_Distinct_TSource_1 ??= new Func, IQueryable>(Queryable.Distinct).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Distinct_TSource_2; public static MethodInfo Distinct_TSource_2(Type TSource) => - (s_Distinct_TSource_2 ?? - (s_Distinct_TSource_2 = new Func, IEqualityComparer, IQueryable>(Queryable.Distinct).GetMethodInfo().GetGenericMethodDefinition())) + (s_Distinct_TSource_2 ??= new Func, IEqualityComparer, IQueryable>(Queryable.Distinct).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); - private static MethodInfo? s_ElementAt_TSource_2; + private static MethodInfo? s_ElementAt_Int32_TSource_2; - public static MethodInfo ElementAt_TSource_2(Type TSource) => - (s_ElementAt_TSource_2 ?? - (s_ElementAt_TSource_2 = new Func, int, object>(Queryable.ElementAt).GetMethodInfo().GetGenericMethodDefinition())) + public static MethodInfo ElementAt_Int32_TSource_2(Type TSource) => + (s_ElementAt_Int32_TSource_2 ??= new Func, int, object>(Queryable.ElementAt).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); - private static MethodInfo? s_ElementAtOrDefault_TSource_2; + private static MethodInfo? s_ElementAt_Index_TSource_2; - public static MethodInfo ElementAtOrDefault_TSource_2(Type TSource) => - (s_ElementAtOrDefault_TSource_2 ?? - (s_ElementAtOrDefault_TSource_2 = new Func, int, object?>(Queryable.ElementAtOrDefault).GetMethodInfo().GetGenericMethodDefinition())) + public static MethodInfo ElementAt_Index_TSource_2(Type TSource) => + (s_ElementAt_Index_TSource_2 ??= new Func, Index, object>(Queryable.ElementAt).GetMethodInfo().GetGenericMethodDefinition()) + .MakeGenericMethod(TSource); + + private static MethodInfo? s_ElementAtOrDefault_Int32_TSource_2; + + public static MethodInfo ElementAtOrDefault_Int32_TSource_2(Type TSource) => + (s_ElementAtOrDefault_Int32_TSource_2 ??= new Func, int, object?>(Queryable.ElementAtOrDefault).GetMethodInfo().GetGenericMethodDefinition()) + .MakeGenericMethod(TSource); + + private static MethodInfo? s_ElementAtOrDefault_Index_TSource_2; + + public static MethodInfo ElementAtOrDefault_Index_TSource_2(Type TSource) => + (s_ElementAtOrDefault_Index_TSource_2 ??= new Func, Index, object?>(Queryable.ElementAtOrDefault).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Except_TSource_2; public static MethodInfo Except_TSource_2(Type TSource) => - (s_Except_TSource_2 ?? - (s_Except_TSource_2 = new Func, IEnumerable, IQueryable>(Queryable.Except).GetMethodInfo().GetGenericMethodDefinition())) + (s_Except_TSource_2 ??= new Func, IEnumerable, IQueryable>(Queryable.Except).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Except_TSource_3; public static MethodInfo Except_TSource_3(Type TSource) => - (s_Except_TSource_3 ?? - (s_Except_TSource_3 = new Func, IEnumerable, IEqualityComparer, IQueryable>(Queryable.Except).GetMethodInfo().GetGenericMethodDefinition())) + (s_Except_TSource_3 ??= new Func, IEnumerable, IEqualityComparer, IQueryable>(Queryable.Except).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_First_TSource_1; public static MethodInfo First_TSource_1(Type TSource) => - (s_First_TSource_1 ?? - (s_First_TSource_1 = new Func, object>(Queryable.First).GetMethodInfo().GetGenericMethodDefinition())) + (s_First_TSource_1 ??= new Func, object>(Queryable.First).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_First_TSource_2; public static MethodInfo First_TSource_2(Type TSource) => - (s_First_TSource_2 ?? - (s_First_TSource_2 = new Func, Expression>, object>(Queryable.First).GetMethodInfo().GetGenericMethodDefinition())) + (s_First_TSource_2 ??= new Func, Expression>, object>(Queryable.First).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_FirstOrDefault_TSource_1; public static MethodInfo FirstOrDefault_TSource_1(Type TSource) => - (s_FirstOrDefault_TSource_1 ?? - (s_FirstOrDefault_TSource_1 = new Func, object?>(Queryable.FirstOrDefault).GetMethodInfo().GetGenericMethodDefinition())) + (s_FirstOrDefault_TSource_1 ??= new Func, object?>(Queryable.FirstOrDefault).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_FirstOrDefault_TSource_2; public static MethodInfo FirstOrDefault_TSource_2(Type TSource) => - (s_FirstOrDefault_TSource_2 ?? - (s_FirstOrDefault_TSource_2 = new Func, Expression>, object?>(Queryable.FirstOrDefault).GetMethodInfo().GetGenericMethodDefinition())) + (s_FirstOrDefault_TSource_2 ??= new Func, Expression>, object?>(Queryable.FirstOrDefault).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_GroupBy_TSource_TKey_2; public static MethodInfo GroupBy_TSource_TKey_2(Type TSource, Type TKey) => - (s_GroupBy_TSource_TKey_2 ?? - (s_GroupBy_TSource_TKey_2 = new Func, Expression>, IQueryable>>(Queryable.GroupBy).GetMethodInfo().GetGenericMethodDefinition())) + (s_GroupBy_TSource_TKey_2 ??= new Func, Expression>, IQueryable>>(Queryable.GroupBy).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TKey); private static MethodInfo? s_GroupBy_TSource_TKey_3; public static MethodInfo GroupBy_TSource_TKey_3(Type TSource, Type TKey) => - (s_GroupBy_TSource_TKey_3 ?? - (s_GroupBy_TSource_TKey_3 = new Func, Expression>, IEqualityComparer, IQueryable>>(Queryable.GroupBy).GetMethodInfo().GetGenericMethodDefinition())) + (s_GroupBy_TSource_TKey_3 ??= new Func, Expression>, IEqualityComparer, IQueryable>>(Queryable.GroupBy).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TKey); private static MethodInfo? s_GroupBy_TSource_TKey_TElement_3; public static MethodInfo GroupBy_TSource_TKey_TElement_3(Type TSource, Type TKey, Type TElement) => - (s_GroupBy_TSource_TKey_TElement_3 ?? - (s_GroupBy_TSource_TKey_TElement_3 = new Func, Expression>, Expression>, IQueryable>>(Queryable.GroupBy).GetMethodInfo().GetGenericMethodDefinition())) + (s_GroupBy_TSource_TKey_TElement_3 ??= new Func, Expression>, Expression>, IQueryable>>(Queryable.GroupBy).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TKey, TElement); private static MethodInfo? s_GroupBy_TSource_TKey_TElement_4; public static MethodInfo GroupBy_TSource_TKey_TElement_4(Type TSource, Type TKey, Type TElement) => - (s_GroupBy_TSource_TKey_TElement_4 ?? - (s_GroupBy_TSource_TKey_TElement_4 = new Func, Expression>, Expression>, IEqualityComparer, IQueryable>>(Queryable.GroupBy).GetMethodInfo().GetGenericMethodDefinition())) + (s_GroupBy_TSource_TKey_TElement_4 ??= new Func, Expression>, Expression>, IEqualityComparer, IQueryable>>(Queryable.GroupBy).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TKey, TElement); private static MethodInfo? s_GroupBy_TSource_TKey_TResult_3; public static MethodInfo GroupBy_TSource_TKey_TResult_3(Type TSource, Type TKey, Type TResult) => - (s_GroupBy_TSource_TKey_TResult_3 ?? - (s_GroupBy_TSource_TKey_TResult_3 = new Func, Expression>, Expression, object>>, IQueryable>(Queryable.GroupBy).GetMethodInfo().GetGenericMethodDefinition())) + (s_GroupBy_TSource_TKey_TResult_3 ??= new Func, Expression>, Expression, object>>, IQueryable>(Queryable.GroupBy).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TKey, TResult); private static MethodInfo? s_GroupBy_TSource_TKey_TResult_4; public static MethodInfo GroupBy_TSource_TKey_TResult_4(Type TSource, Type TKey, Type TResult) => - (s_GroupBy_TSource_TKey_TResult_4 ?? - (s_GroupBy_TSource_TKey_TResult_4 = new Func, Expression>, Expression, object>>, IEqualityComparer, IQueryable>(Queryable.GroupBy).GetMethodInfo().GetGenericMethodDefinition())) + (s_GroupBy_TSource_TKey_TResult_4 ??= new Func, Expression>, Expression, object>>, IEqualityComparer, IQueryable>(Queryable.GroupBy).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TKey, TResult); private static MethodInfo? s_GroupBy_TSource_TKey_TElement_TResult_4; public static MethodInfo GroupBy_TSource_TKey_TElement_TResult_4(Type TSource, Type TKey, Type TElement, Type TResult) => - (s_GroupBy_TSource_TKey_TElement_TResult_4 ?? - (s_GroupBy_TSource_TKey_TElement_TResult_4 = new Func, Expression>, Expression>, Expression, object>>, IQueryable>(Queryable.GroupBy).GetMethodInfo().GetGenericMethodDefinition())) + (s_GroupBy_TSource_TKey_TElement_TResult_4 ??= new Func, Expression>, Expression>, Expression, object>>, IQueryable>(Queryable.GroupBy).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TKey, TElement, TResult); private static MethodInfo? s_GroupBy_TSource_TKey_TElement_TResult_5; public static MethodInfo GroupBy_TSource_TKey_TElement_TResult_5(Type TSource, Type TKey, Type TElement, Type TResult) => - (s_GroupBy_TSource_TKey_TElement_TResult_5 ?? - (s_GroupBy_TSource_TKey_TElement_TResult_5 = new Func, Expression>, Expression>, Expression, object>>, IEqualityComparer, IQueryable>(Queryable.GroupBy).GetMethodInfo().GetGenericMethodDefinition())) + (s_GroupBy_TSource_TKey_TElement_TResult_5 ??= new Func, Expression>, Expression>, Expression, object>>, IEqualityComparer, IQueryable>(Queryable.GroupBy).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TKey, TElement, TResult); private static MethodInfo? s_GroupJoin_TOuter_TInner_TKey_TResult_5; public static MethodInfo GroupJoin_TOuter_TInner_TKey_TResult_5(Type TOuter, Type TInner, Type TKey, Type TResult) => - (s_GroupJoin_TOuter_TInner_TKey_TResult_5 ?? - (s_GroupJoin_TOuter_TInner_TKey_TResult_5 = new Func, IEnumerable, Expression>, Expression>, Expression, object>>, IQueryable>(Queryable.GroupJoin).GetMethodInfo().GetGenericMethodDefinition())) + (s_GroupJoin_TOuter_TInner_TKey_TResult_5 ??= new Func, IEnumerable, Expression>, Expression>, Expression, object>>, IQueryable>(Queryable.GroupJoin).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TOuter, TInner, TKey, TResult); private static MethodInfo? s_GroupJoin_TOuter_TInner_TKey_TResult_6; public static MethodInfo GroupJoin_TOuter_TInner_TKey_TResult_6(Type TOuter, Type TInner, Type TKey, Type TResult) => - (s_GroupJoin_TOuter_TInner_TKey_TResult_6 ?? - (s_GroupJoin_TOuter_TInner_TKey_TResult_6 = new Func, IEnumerable, Expression>, Expression>, Expression, object>>, IEqualityComparer, IQueryable>(Queryable.GroupJoin).GetMethodInfo().GetGenericMethodDefinition())) + (s_GroupJoin_TOuter_TInner_TKey_TResult_6 ??= new Func, IEnumerable, Expression>, Expression>, Expression, object>>, IEqualityComparer, IQueryable>(Queryable.GroupJoin).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TOuter, TInner, TKey, TResult); private static MethodInfo? s_Intersect_TSource_2; public static MethodInfo Intersect_TSource_2(Type TSource) => - (s_Intersect_TSource_2 ?? - (s_Intersect_TSource_2 = new Func, IEnumerable, IQueryable>(Queryable.Intersect).GetMethodInfo().GetGenericMethodDefinition())) + (s_Intersect_TSource_2 ??= new Func, IEnumerable, IQueryable>(Queryable.Intersect).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Intersect_TSource_3; public static MethodInfo Intersect_TSource_3(Type TSource) => - (s_Intersect_TSource_3 ?? - (s_Intersect_TSource_3 = new Func, IEnumerable, IEqualityComparer, IQueryable>(Queryable.Intersect).GetMethodInfo().GetGenericMethodDefinition())) + (s_Intersect_TSource_3 ??= new Func, IEnumerable, IEqualityComparer, IQueryable>(Queryable.Intersect).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Join_TOuter_TInner_TKey_TResult_5; public static MethodInfo Join_TOuter_TInner_TKey_TResult_5(Type TOuter, Type TInner, Type TKey, Type TResult) => - (s_Join_TOuter_TInner_TKey_TResult_5 ?? - (s_Join_TOuter_TInner_TKey_TResult_5 = new Func, IEnumerable, Expression>, Expression>, Expression>, IQueryable>(Queryable.Join).GetMethodInfo().GetGenericMethodDefinition())) + (s_Join_TOuter_TInner_TKey_TResult_5 ??= new Func, IEnumerable, Expression>, Expression>, Expression>, IQueryable>(Queryable.Join).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TOuter, TInner, TKey, TResult); private static MethodInfo? s_Join_TOuter_TInner_TKey_TResult_6; public static MethodInfo Join_TOuter_TInner_TKey_TResult_6(Type TOuter, Type TInner, Type TKey, Type TResult) => - (s_Join_TOuter_TInner_TKey_TResult_6 ?? - (s_Join_TOuter_TInner_TKey_TResult_6 = new Func, IEnumerable, Expression>, Expression>, Expression>, IEqualityComparer, IQueryable>(Queryable.Join).GetMethodInfo().GetGenericMethodDefinition())) + (s_Join_TOuter_TInner_TKey_TResult_6 ??= new Func, IEnumerable, Expression>, Expression>, Expression>, IEqualityComparer, IQueryable>(Queryable.Join).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TOuter, TInner, TKey, TResult); private static MethodInfo? s_Last_TSource_1; public static MethodInfo Last_TSource_1(Type TSource) => - (s_Last_TSource_1 ?? - (s_Last_TSource_1 = new Func, object>(Queryable.Last).GetMethodInfo().GetGenericMethodDefinition())) + (s_Last_TSource_1 ??= new Func, object>(Queryable.Last).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Last_TSource_2; public static MethodInfo Last_TSource_2(Type TSource) => - (s_Last_TSource_2 ?? - (s_Last_TSource_2 = new Func, Expression>, object>(Queryable.Last).GetMethodInfo().GetGenericMethodDefinition())) + (s_Last_TSource_2 ??= new Func, Expression>, object>(Queryable.Last).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_LastOrDefault_TSource_1; public static MethodInfo LastOrDefault_TSource_1(Type TSource) => - (s_LastOrDefault_TSource_1 ?? - (s_LastOrDefault_TSource_1 = new Func, object?>(Queryable.LastOrDefault).GetMethodInfo().GetGenericMethodDefinition())) + (s_LastOrDefault_TSource_1 ??= new Func, object?>(Queryable.LastOrDefault).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_LastOrDefault_TSource_2; public static MethodInfo LastOrDefault_TSource_2(Type TSource) => - (s_LastOrDefault_TSource_2 ?? - (s_LastOrDefault_TSource_2 = new Func, Expression>, object?>(Queryable.LastOrDefault).GetMethodInfo().GetGenericMethodDefinition())) + (s_LastOrDefault_TSource_2 ??= new Func, Expression>, object?>(Queryable.LastOrDefault).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_LongCount_TSource_1; public static MethodInfo LongCount_TSource_1(Type TSource) => - (s_LongCount_TSource_1 ?? - (s_LongCount_TSource_1 = new Func, long>(Queryable.LongCount).GetMethodInfo().GetGenericMethodDefinition())) + (s_LongCount_TSource_1 ??= new Func, long>(Queryable.LongCount).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_LongCount_TSource_2; public static MethodInfo LongCount_TSource_2(Type TSource) => - (s_LongCount_TSource_2 ?? - (s_LongCount_TSource_2 = new Func, Expression>, long>(Queryable.LongCount).GetMethodInfo().GetGenericMethodDefinition())) + (s_LongCount_TSource_2 ??= new Func, Expression>, long>(Queryable.LongCount).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Max_TSource_1; public static MethodInfo Max_TSource_1(Type TSource) => - (s_Max_TSource_1 ?? - (s_Max_TSource_1 = new Func, object?>(Queryable.Max).GetMethodInfo().GetGenericMethodDefinition())) + (s_Max_TSource_1 ??= new Func, object?>(Queryable.Max).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Max_TSource_TResult_2; public static MethodInfo Max_TSource_TResult_2(Type TSource, Type TResult) => - (s_Max_TSource_TResult_2 ?? - (s_Max_TSource_TResult_2 = new Func, Expression>, object?>(Queryable.Max).GetMethodInfo().GetGenericMethodDefinition())) + (s_Max_TSource_TResult_2 ??= new Func, Expression>, object?>(Queryable.Max).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TResult); private static MethodInfo? s_Min_TSource_1; public static MethodInfo Min_TSource_1(Type TSource) => - (s_Min_TSource_1 ?? - (s_Min_TSource_1 = new Func, object?>(Queryable.Min).GetMethodInfo().GetGenericMethodDefinition())) + (s_Min_TSource_1 ??= new Func, object?>(Queryable.Min).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Min_TSource_TResult_2; public static MethodInfo Min_TSource_TResult_2(Type TSource, Type TResult) => - (s_Min_TSource_TResult_2 ?? - (s_Min_TSource_TResult_2 = new Func, Expression>, object?>(Queryable.Min).GetMethodInfo().GetGenericMethodDefinition())) + (s_Min_TSource_TResult_2 ??= new Func, Expression>, object?>(Queryable.Min).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TResult); private static MethodInfo? s_OfType_TResult_1; public static MethodInfo OfType_TResult_1(Type TResult) => - (s_OfType_TResult_1 ?? - (s_OfType_TResult_1 = new Func>(Queryable.OfType).GetMethodInfo().GetGenericMethodDefinition())) + (s_OfType_TResult_1 ??= new Func>(Queryable.OfType).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TResult); private static MethodInfo? s_OrderBy_TSource_TKey_2; public static MethodInfo OrderBy_TSource_TKey_2(Type TSource, Type TKey) => - (s_OrderBy_TSource_TKey_2 ?? - (s_OrderBy_TSource_TKey_2 = new Func, Expression>, IOrderedQueryable>(Queryable.OrderBy).GetMethodInfo().GetGenericMethodDefinition())) + (s_OrderBy_TSource_TKey_2 ??= new Func, Expression>, IOrderedQueryable>(Queryable.OrderBy).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TKey); private static MethodInfo? s_OrderBy_TSource_TKey_3; public static MethodInfo OrderBy_TSource_TKey_3(Type TSource, Type TKey) => - (s_OrderBy_TSource_TKey_3 ?? - (s_OrderBy_TSource_TKey_3 = new Func, Expression>, IComparer, IOrderedQueryable>(Queryable.OrderBy).GetMethodInfo().GetGenericMethodDefinition())) + (s_OrderBy_TSource_TKey_3 ??= new Func, Expression>, IComparer, IOrderedQueryable>(Queryable.OrderBy).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TKey); private static MethodInfo? s_OrderByDescending_TSource_TKey_2; public static MethodInfo OrderByDescending_TSource_TKey_2(Type TSource, Type TKey) => - (s_OrderByDescending_TSource_TKey_2 ?? - (s_OrderByDescending_TSource_TKey_2 = new Func, Expression>, IOrderedQueryable>(Queryable.OrderByDescending).GetMethodInfo().GetGenericMethodDefinition())) + (s_OrderByDescending_TSource_TKey_2 ??= new Func, Expression>, IOrderedQueryable>(Queryable.OrderByDescending).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TKey); private static MethodInfo? s_OrderByDescending_TSource_TKey_3; public static MethodInfo OrderByDescending_TSource_TKey_3(Type TSource, Type TKey) => - (s_OrderByDescending_TSource_TKey_3 ?? - (s_OrderByDescending_TSource_TKey_3 = new Func, Expression>, IComparer, IOrderedQueryable>(Queryable.OrderByDescending).GetMethodInfo().GetGenericMethodDefinition())) + (s_OrderByDescending_TSource_TKey_3 ??= new Func, Expression>, IComparer, IOrderedQueryable>(Queryable.OrderByDescending).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TKey); private static MethodInfo? s_Reverse_TSource_1; public static MethodInfo Reverse_TSource_1(Type TSource) => - (s_Reverse_TSource_1 ?? - (s_Reverse_TSource_1 = new Func, IQueryable>(Queryable.Reverse).GetMethodInfo().GetGenericMethodDefinition())) + (s_Reverse_TSource_1 ??= new Func, IQueryable>(Queryable.Reverse).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Select_TSource_TResult_2; public static MethodInfo Select_TSource_TResult_2(Type TSource, Type TResult) => - (s_Select_TSource_TResult_2 ?? - (s_Select_TSource_TResult_2 = new Func, Expression>, IQueryable>(Queryable.Select).GetMethodInfo().GetGenericMethodDefinition())) + (s_Select_TSource_TResult_2 ??= new Func, Expression>, IQueryable>(Queryable.Select).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TResult); private static MethodInfo? s_Select_Index_TSource_TResult_2; public static MethodInfo Select_Index_TSource_TResult_2(Type TSource, Type TResult) => - (s_Select_Index_TSource_TResult_2 ?? - (s_Select_Index_TSource_TResult_2 = new Func, Expression>, IQueryable>(Queryable.Select).GetMethodInfo().GetGenericMethodDefinition())) + (s_Select_Index_TSource_TResult_2 ??= new Func, Expression>, IQueryable>(Queryable.Select).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TResult); private static MethodInfo? s_SelectMany_TSource_TResult_2; public static MethodInfo SelectMany_TSource_TResult_2(Type TSource, Type TResult) => - (s_SelectMany_TSource_TResult_2 ?? - (s_SelectMany_TSource_TResult_2 = new Func, Expression>>, IQueryable>(Queryable.SelectMany).GetMethodInfo().GetGenericMethodDefinition())) + (s_SelectMany_TSource_TResult_2 ??= new Func, Expression>>, IQueryable>(Queryable.SelectMany).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TResult); private static MethodInfo? s_SelectMany_Index_TSource_TResult_2; public static MethodInfo SelectMany_Index_TSource_TResult_2(Type TSource, Type TResult) => - (s_SelectMany_Index_TSource_TResult_2 ?? - (s_SelectMany_Index_TSource_TResult_2 = new Func, Expression>>, IQueryable>(Queryable.SelectMany).GetMethodInfo().GetGenericMethodDefinition())) + (s_SelectMany_Index_TSource_TResult_2 ??= new Func, Expression>>, IQueryable>(Queryable.SelectMany).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TResult); private static MethodInfo? s_SelectMany_Index_TSource_TCollection_TResult_3; public static MethodInfo SelectMany_Index_TSource_TCollection_TResult_3(Type TSource, Type TCollection, Type TResult) => - (s_SelectMany_Index_TSource_TCollection_TResult_3 ?? - (s_SelectMany_Index_TSource_TCollection_TResult_3 = new Func, Expression>>, Expression>, IQueryable>(Queryable.SelectMany).GetMethodInfo().GetGenericMethodDefinition())) + (s_SelectMany_Index_TSource_TCollection_TResult_3 ??= new Func, Expression>>, Expression>, IQueryable>(Queryable.SelectMany).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TCollection, TResult); private static MethodInfo? s_SelectMany_TSource_TCollection_TResult_3; public static MethodInfo SelectMany_TSource_TCollection_TResult_3(Type TSource, Type TCollection, Type TResult) => - (s_SelectMany_TSource_TCollection_TResult_3 ?? - (s_SelectMany_TSource_TCollection_TResult_3 = new Func, Expression>>, Expression>, IQueryable>(Queryable.SelectMany).GetMethodInfo().GetGenericMethodDefinition())) + (s_SelectMany_TSource_TCollection_TResult_3 ??= new Func, Expression>>, Expression>, IQueryable>(Queryable.SelectMany).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TCollection, TResult); private static MethodInfo? s_SequenceEqual_TSource_2; public static MethodInfo SequenceEqual_TSource_2(Type TSource) => - (s_SequenceEqual_TSource_2 ?? - (s_SequenceEqual_TSource_2 = new Func, IEnumerable, bool>(Queryable.SequenceEqual).GetMethodInfo().GetGenericMethodDefinition())) + (s_SequenceEqual_TSource_2 ??= new Func, IEnumerable, bool>(Queryable.SequenceEqual).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_SequenceEqual_TSource_3; public static MethodInfo SequenceEqual_TSource_3(Type TSource) => - (s_SequenceEqual_TSource_3 ?? - (s_SequenceEqual_TSource_3 = new Func, IEnumerable, IEqualityComparer, bool>(Queryable.SequenceEqual).GetMethodInfo().GetGenericMethodDefinition())) + (s_SequenceEqual_TSource_3 ??= new Func, IEnumerable, IEqualityComparer, bool>(Queryable.SequenceEqual).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Single_TSource_1; public static MethodInfo Single_TSource_1(Type TSource) => - (s_Single_TSource_1 ?? - (s_Single_TSource_1 = new Func, object>(Queryable.Single).GetMethodInfo().GetGenericMethodDefinition())) + (s_Single_TSource_1 ??= new Func, object>(Queryable.Single).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Single_TSource_2; public static MethodInfo Single_TSource_2(Type TSource) => - (s_Single_TSource_2 ?? - (s_Single_TSource_2 = new Func, Expression>, object>(Queryable.Single).GetMethodInfo().GetGenericMethodDefinition())) + (s_Single_TSource_2 ??= new Func, Expression>, object>(Queryable.Single).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_SingleOrDefault_TSource_1; public static MethodInfo SingleOrDefault_TSource_1(Type TSource) => - (s_SingleOrDefault_TSource_1 ?? - (s_SingleOrDefault_TSource_1 = new Func, object?>(Queryable.SingleOrDefault).GetMethodInfo().GetGenericMethodDefinition())) + (s_SingleOrDefault_TSource_1 ??= new Func, object?>(Queryable.SingleOrDefault).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_SingleOrDefault_TSource_2; public static MethodInfo SingleOrDefault_TSource_2(Type TSource) => - (s_SingleOrDefault_TSource_2 ?? - (s_SingleOrDefault_TSource_2 = new Func, Expression>, object?>(Queryable.SingleOrDefault).GetMethodInfo().GetGenericMethodDefinition())) + (s_SingleOrDefault_TSource_2 ??= new Func, Expression>, object?>(Queryable.SingleOrDefault).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Skip_TSource_2; public static MethodInfo Skip_TSource_2(Type TSource) => - (s_Skip_TSource_2 ?? - (s_Skip_TSource_2 = new Func, int, IQueryable>(Queryable.Skip).GetMethodInfo().GetGenericMethodDefinition())) + (s_Skip_TSource_2 ??= new Func, int, IQueryable>(Queryable.Skip).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_SkipWhile_TSource_2; public static MethodInfo SkipWhile_TSource_2(Type TSource) => - (s_SkipWhile_TSource_2 ?? - (s_SkipWhile_TSource_2 = new Func, Expression>, IQueryable>(Queryable.SkipWhile).GetMethodInfo().GetGenericMethodDefinition())) + (s_SkipWhile_TSource_2 ??= new Func, Expression>, IQueryable>(Queryable.SkipWhile).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_SkipWhile_Index_TSource_2; public static MethodInfo SkipWhile_Index_TSource_2(Type TSource) => - (s_SkipWhile_Index_TSource_2 ?? - (s_SkipWhile_Index_TSource_2 = new Func, Expression>, IQueryable>(Queryable.SkipWhile).GetMethodInfo().GetGenericMethodDefinition())) + (s_SkipWhile_Index_TSource_2 ??= new Func, Expression>, IQueryable>(Queryable.SkipWhile).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Sum_Int32_1; public static MethodInfo Sum_Int32_1 => - s_Sum_Int32_1 ?? - (s_Sum_Int32_1 = new Func, int>(Queryable.Sum).GetMethodInfo()); + s_Sum_Int32_1 ??= new Func, int>(Queryable.Sum).GetMethodInfo(); private static MethodInfo? s_Sum_NullableInt32_1; public static MethodInfo Sum_NullableInt32_1 => - s_Sum_NullableInt32_1 ?? - (s_Sum_NullableInt32_1 = new Func, int?>(Queryable.Sum).GetMethodInfo()); + s_Sum_NullableInt32_1 ??= new Func, int?>(Queryable.Sum).GetMethodInfo(); private static MethodInfo? s_Sum_Int64_1; public static MethodInfo Sum_Int64_1 => - s_Sum_Int64_1 ?? - (s_Sum_Int64_1 = new Func, long>(Queryable.Sum).GetMethodInfo()); + s_Sum_Int64_1 ??= new Func, long>(Queryable.Sum).GetMethodInfo(); private static MethodInfo? s_Sum_NullableInt64_1; public static MethodInfo Sum_NullableInt64_1 => - s_Sum_NullableInt64_1 ?? - (s_Sum_NullableInt64_1 = new Func, long?>(Queryable.Sum).GetMethodInfo()); + s_Sum_NullableInt64_1 ??= new Func, long?>(Queryable.Sum).GetMethodInfo(); private static MethodInfo? s_Sum_Single_1; public static MethodInfo Sum_Single_1 => - s_Sum_Single_1 ?? - (s_Sum_Single_1 = new Func, float>(Queryable.Sum).GetMethodInfo()); + s_Sum_Single_1 ??= new Func, float>(Queryable.Sum).GetMethodInfo(); private static MethodInfo? s_Sum_NullableSingle_1; public static MethodInfo Sum_NullableSingle_1 => - s_Sum_NullableSingle_1 ?? - (s_Sum_NullableSingle_1 = new Func, float?>(Queryable.Sum).GetMethodInfo()); + s_Sum_NullableSingle_1 ??= new Func, float?>(Queryable.Sum).GetMethodInfo(); private static MethodInfo? s_Sum_Double_1; public static MethodInfo Sum_Double_1 => - s_Sum_Double_1 ?? - (s_Sum_Double_1 = new Func, double>(Queryable.Sum).GetMethodInfo()); + s_Sum_Double_1 ??= new Func, double>(Queryable.Sum).GetMethodInfo(); private static MethodInfo? s_Sum_NullableDouble_1; public static MethodInfo Sum_NullableDouble_1 => - s_Sum_NullableDouble_1 ?? - (s_Sum_NullableDouble_1 = new Func, double?>(Queryable.Sum).GetMethodInfo()); + s_Sum_NullableDouble_1 ??= new Func, double?>(Queryable.Sum).GetMethodInfo(); private static MethodInfo? s_Sum_Decimal_1; public static MethodInfo Sum_Decimal_1 => - s_Sum_Decimal_1 ?? - (s_Sum_Decimal_1 = new Func, decimal>(Queryable.Sum).GetMethodInfo()); + s_Sum_Decimal_1 ??= new Func, decimal>(Queryable.Sum).GetMethodInfo(); private static MethodInfo? s_Sum_NullableDecimal_1; public static MethodInfo Sum_NullableDecimal_1 => - s_Sum_NullableDecimal_1 ?? - (s_Sum_NullableDecimal_1 = new Func, decimal?>(Queryable.Sum).GetMethodInfo()); + s_Sum_NullableDecimal_1 ??= new Func, decimal?>(Queryable.Sum).GetMethodInfo(); private static MethodInfo? s_Sum_NullableDecimal_TSource_2; public static MethodInfo Sum_NullableDecimal_TSource_2(Type TSource) => - (s_Sum_NullableDecimal_TSource_2 ?? - (s_Sum_NullableDecimal_TSource_2 = new Func, Expression>, decimal?>(Queryable.Sum).GetMethodInfo().GetGenericMethodDefinition())) + (s_Sum_NullableDecimal_TSource_2 ??= new Func, Expression>, decimal?>(Queryable.Sum).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Sum_Int32_TSource_2; public static MethodInfo Sum_Int32_TSource_2(Type TSource) => - (s_Sum_Int32_TSource_2 ?? - (s_Sum_Int32_TSource_2 = new Func, Expression>, int>(Queryable.Sum).GetMethodInfo().GetGenericMethodDefinition())) + (s_Sum_Int32_TSource_2 ??= new Func, Expression>, int>(Queryable.Sum).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Sum_NullableInt32_TSource_2; public static MethodInfo Sum_NullableInt32_TSource_2(Type TSource) => - (s_Sum_NullableInt32_TSource_2 ?? - (s_Sum_NullableInt32_TSource_2 = new Func, Expression>, int?>(Queryable.Sum).GetMethodInfo().GetGenericMethodDefinition())) + (s_Sum_NullableInt32_TSource_2 ??= new Func, Expression>, int?>(Queryable.Sum).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Sum_Int64_TSource_2; public static MethodInfo Sum_Int64_TSource_2(Type TSource) => - (s_Sum_Int64_TSource_2 ?? - (s_Sum_Int64_TSource_2 = new Func, Expression>, long>(Queryable.Sum).GetMethodInfo().GetGenericMethodDefinition())) + (s_Sum_Int64_TSource_2 ??= new Func, Expression>, long>(Queryable.Sum).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Sum_NullableInt64_TSource_2; public static MethodInfo Sum_NullableInt64_TSource_2(Type TSource) => - (s_Sum_NullableInt64_TSource_2 ?? - (s_Sum_NullableInt64_TSource_2 = new Func, Expression>, long?>(Queryable.Sum).GetMethodInfo().GetGenericMethodDefinition())) + (s_Sum_NullableInt64_TSource_2 ??= new Func, Expression>, long?>(Queryable.Sum).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Sum_Single_TSource_2; public static MethodInfo Sum_Single_TSource_2(Type TSource) => - (s_Sum_Single_TSource_2 ?? - (s_Sum_Single_TSource_2 = new Func, Expression>, float>(Queryable.Sum).GetMethodInfo().GetGenericMethodDefinition())) + (s_Sum_Single_TSource_2 ??= new Func, Expression>, float>(Queryable.Sum).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Sum_NullableSingle_TSource_2; public static MethodInfo Sum_NullableSingle_TSource_2(Type TSource) => - (s_Sum_NullableSingle_TSource_2 ?? - (s_Sum_NullableSingle_TSource_2 = new Func, Expression>, float?>(Queryable.Sum).GetMethodInfo().GetGenericMethodDefinition())) + (s_Sum_NullableSingle_TSource_2 ??= new Func, Expression>, float?>(Queryable.Sum).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Sum_Double_TSource_2; public static MethodInfo Sum_Double_TSource_2(Type TSource) => - (s_Sum_Double_TSource_2 ?? - (s_Sum_Double_TSource_2 = new Func, Expression>, double>(Queryable.Sum).GetMethodInfo().GetGenericMethodDefinition())) + (s_Sum_Double_TSource_2 ??= new Func, Expression>, double>(Queryable.Sum).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Sum_NullableDouble_TSource_2; public static MethodInfo Sum_NullableDouble_TSource_2(Type TSource) => - (s_Sum_NullableDouble_TSource_2 ?? - (s_Sum_NullableDouble_TSource_2 = new Func, Expression>, double?>(Queryable.Sum).GetMethodInfo().GetGenericMethodDefinition())) + (s_Sum_NullableDouble_TSource_2 ??= new Func, Expression>, double?>(Queryable.Sum).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Sum_Decimal_TSource_2; public static MethodInfo Sum_Decimal_TSource_2(Type TSource) => - (s_Sum_Decimal_TSource_2 ?? - (s_Sum_Decimal_TSource_2 = new Func, Expression>, decimal>(Queryable.Sum).GetMethodInfo().GetGenericMethodDefinition())) + (s_Sum_Decimal_TSource_2 ??= new Func, Expression>, decimal>(Queryable.Sum).GetMethodInfo().GetGenericMethodDefinition()) + .MakeGenericMethod(TSource); + + private static MethodInfo? s_Take_Int32_TSource_2; + + public static MethodInfo Take_Int32_TSource_2(Type TSource) => + (s_Take_Int32_TSource_2 ??= new Func, int, IQueryable>(Queryable.Take).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); - private static MethodInfo? s_Take_TSource_2; + private static MethodInfo? s_Take_Range_TSource_2; - public static MethodInfo Take_TSource_2(Type TSource) => - (s_Take_TSource_2 ?? - (s_Take_TSource_2 = new Func, int, IQueryable>(Queryable.Take).GetMethodInfo().GetGenericMethodDefinition())) + public static MethodInfo Take_Range_TSource_2(Type TSource) => + (s_Take_Range_TSource_2 ??= new Func, Range, IQueryable>(Queryable.Take).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_TakeWhile_TSource_2; public static MethodInfo TakeWhile_TSource_2(Type TSource) => - (s_TakeWhile_TSource_2 ?? - (s_TakeWhile_TSource_2 = new Func, Expression>, IQueryable>(Queryable.TakeWhile).GetMethodInfo().GetGenericMethodDefinition())) + (s_TakeWhile_TSource_2 ??= new Func, Expression>, IQueryable>(Queryable.TakeWhile).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_TakeWhile_Index_TSource_2; public static MethodInfo TakeWhile_Index_TSource_2(Type TSource) => - (s_TakeWhile_Index_TSource_2 ?? - (s_TakeWhile_Index_TSource_2 = new Func, Expression>, IQueryable>(Queryable.TakeWhile).GetMethodInfo().GetGenericMethodDefinition())) + (s_TakeWhile_Index_TSource_2 ??= new Func, Expression>, IQueryable>(Queryable.TakeWhile).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_ThenBy_TSource_TKey_2; public static MethodInfo ThenBy_TSource_TKey_2(Type TSource, Type TKey) => - (s_ThenBy_TSource_TKey_2 ?? - (s_ThenBy_TSource_TKey_2 = new Func, Expression>, IOrderedQueryable>(Queryable.ThenBy).GetMethodInfo().GetGenericMethodDefinition())) + (s_ThenBy_TSource_TKey_2 ??= new Func, Expression>, IOrderedQueryable>(Queryable.ThenBy).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TKey); private static MethodInfo? s_ThenBy_TSource_TKey_3; public static MethodInfo ThenBy_TSource_TKey_3(Type TSource, Type TKey) => - (s_ThenBy_TSource_TKey_3 ?? - (s_ThenBy_TSource_TKey_3 = new Func, Expression>, IComparer, IOrderedQueryable>(Queryable.ThenBy).GetMethodInfo().GetGenericMethodDefinition())) + (s_ThenBy_TSource_TKey_3 ??= new Func, Expression>, IComparer, IOrderedQueryable>(Queryable.ThenBy).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TKey); private static MethodInfo? s_ThenByDescending_TSource_TKey_2; public static MethodInfo ThenByDescending_TSource_TKey_2(Type TSource, Type TKey) => - (s_ThenByDescending_TSource_TKey_2 ?? - (s_ThenByDescending_TSource_TKey_2 = new Func, Expression>, IOrderedQueryable>(Queryable.ThenByDescending).GetMethodInfo().GetGenericMethodDefinition())) + (s_ThenByDescending_TSource_TKey_2 ??= new Func, Expression>, IOrderedQueryable>(Queryable.ThenByDescending).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TKey); private static MethodInfo? s_ThenByDescending_TSource_TKey_3; public static MethodInfo ThenByDescending_TSource_TKey_3(Type TSource, Type TKey) => - (s_ThenByDescending_TSource_TKey_3 ?? - (s_ThenByDescending_TSource_TKey_3 = new Func, Expression>, IComparer, IOrderedQueryable>(Queryable.ThenByDescending).GetMethodInfo().GetGenericMethodDefinition())) + (s_ThenByDescending_TSource_TKey_3 ??= new Func, Expression>, IComparer, IOrderedQueryable>(Queryable.ThenByDescending).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource, TKey); private static MethodInfo? s_Union_TSource_2; public static MethodInfo Union_TSource_2(Type TSource) => - (s_Union_TSource_2 ?? - (s_Union_TSource_2 = new Func, IEnumerable, IQueryable>(Queryable.Union).GetMethodInfo().GetGenericMethodDefinition())) + (s_Union_TSource_2 ??= new Func, IEnumerable, IQueryable>(Queryable.Union).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Union_TSource_3; public static MethodInfo Union_TSource_3(Type TSource) => - (s_Union_TSource_3 ?? - (s_Union_TSource_3 = new Func, IEnumerable, IEqualityComparer, IQueryable>(Queryable.Union).GetMethodInfo().GetGenericMethodDefinition())) + (s_Union_TSource_3 ??= new Func, IEnumerable, IEqualityComparer, IQueryable>(Queryable.Union).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Where_TSource_2; public static MethodInfo Where_TSource_2(Type TSource) => - (s_Where_TSource_2 ?? - (s_Where_TSource_2 = new Func, Expression>, IQueryable>(Queryable.Where).GetMethodInfo().GetGenericMethodDefinition())) + (s_Where_TSource_2 ??= new Func, Expression>, IQueryable>(Queryable.Where).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Where_Index_TSource_2; public static MethodInfo Where_Index_TSource_2(Type TSource) => - (s_Where_Index_TSource_2 ?? - (s_Where_Index_TSource_2 = new Func, Expression>, IQueryable>(Queryable.Where).GetMethodInfo().GetGenericMethodDefinition())) + (s_Where_Index_TSource_2 ??= new Func, Expression>, IQueryable>(Queryable.Where).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Zip_TFirst_TSecond_2; public static MethodInfo Zip_TFirst_TSecond_2(Type TFirst, Type TSecond) => - (s_Zip_TFirst_TSecond_2 ?? - (s_Zip_TFirst_TSecond_2 = new Func, IEnumerable, IQueryable<(object, object)>>(Queryable.Zip).GetMethodInfo().GetGenericMethodDefinition())) + (s_Zip_TFirst_TSecond_2 ??= new Func, IEnumerable, IQueryable<(object, object)>>(Queryable.Zip).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TFirst, TSecond); private static MethodInfo? s_Zip_TFirst_TSecond_TResult_3; public static MethodInfo Zip_TFirst_TSecond_TResult_3(Type TFirst, Type TSecond, Type TResult) => - (s_Zip_TFirst_TSecond_TResult_3 ?? - (s_Zip_TFirst_TSecond_TResult_3 = new Func, IEnumerable, Expression>, IQueryable>(Queryable.Zip).GetMethodInfo().GetGenericMethodDefinition())) + (s_Zip_TFirst_TSecond_TResult_3 ??= new Func, IEnumerable, Expression>, IQueryable>(Queryable.Zip).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TFirst, TSecond, TResult); private static MethodInfo? s_Zip_TFirst_TSecond_TThird_3; public static MethodInfo Zip_TFirst_TSecond_TThird_3(Type TFirst, Type TSecond, Type TThird) => - (s_Zip_TFirst_TSecond_TThird_3 ?? - (s_Zip_TFirst_TSecond_TThird_3 = new Func, IEnumerable, IEnumerable, IQueryable<(object, object, object)>>(Queryable.Zip).GetMethodInfo().GetGenericMethodDefinition())) + (s_Zip_TFirst_TSecond_TThird_3 ??= new Func, IEnumerable, IEnumerable, IQueryable<(object, object, object)>>(Queryable.Zip).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TFirst, TSecond, TThird); private static MethodInfo? s_SkipLast_TSource_2; public static MethodInfo SkipLast_TSource_2(Type TSource) => - (s_SkipLast_TSource_2 ?? - (s_SkipLast_TSource_2 = new Func, int, IQueryable>(Queryable.SkipLast).GetMethodInfo().GetGenericMethodDefinition())) + (s_SkipLast_TSource_2 ??= new Func, int, IQueryable>(Queryable.SkipLast).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_TakeLast_TSource_2; public static MethodInfo TakeLast_TSource_2(Type TSource) => - (s_TakeLast_TSource_2 ?? - (s_TakeLast_TSource_2 = new Func, int, IQueryable>(Queryable.TakeLast).GetMethodInfo().GetGenericMethodDefinition())) + (s_TakeLast_TSource_2 ??= new Func, int, IQueryable>(Queryable.TakeLast).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Append_TSource_2; public static MethodInfo Append_TSource_2(Type TSource) => - (s_Append_TSource_2 ?? - (s_Append_TSource_2 = new Func, object, IQueryable>(Queryable.Append).GetMethodInfo().GetGenericMethodDefinition())) + (s_Append_TSource_2 ??= new Func, object, IQueryable>(Queryable.Append).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Prepend_TSource_2; public static MethodInfo Prepend_TSource_2(Type TSource) => - (s_Prepend_TSource_2 ?? - (s_Prepend_TSource_2 = new Func, object, IQueryable>(Queryable.Prepend).GetMethodInfo().GetGenericMethodDefinition())) + (s_Prepend_TSource_2 ??= new Func, object, IQueryable>(Queryable.Prepend).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); } } diff --git a/src/libraries/System.Linq.Queryable/src/System/Linq/Queryable.cs b/src/libraries/System.Linq.Queryable/src/System/Linq/Queryable.cs index a4859f68608b8..c08bcab79af79 100644 --- a/src/libraries/System.Linq.Queryable/src/System/Linq/Queryable.cs +++ b/src/libraries/System.Linq.Queryable/src/System/Linq/Queryable.cs @@ -388,11 +388,32 @@ public static IQueryable Take(this IQueryable source, return source.Provider.CreateQuery( Expression.Call( null, - CachedReflectionInfo.Take_TSource_2(typeof(TSource)), + CachedReflectionInfo.Take_Int32_TSource_2(typeof(TSource)), source.Expression, Expression.Constant(count) )); } + /// Returns a specified range of contiguous elements from a sequence. + /// The sequence to return elements from. + /// The range of elements to return, which has start and end indexes either from the start or the end. + /// The type of the elements of . + /// + /// is . + /// + /// An that contains the specified of elements from the sequence. + [DynamicDependency("Take`1", typeof(Enumerable))] + public static IQueryable Take(this IQueryable source, Range range) + { + if (source == null) + throw Error.ArgumentNull(nameof(source)); + return source.Provider.CreateQuery( + Expression.Call( + null, + CachedReflectionInfo.Take_Range_TSource_2(typeof(TSource)), + source.Expression, Expression.Constant(range) + )); + } + [DynamicDependency("TakeWhile`1", typeof(Enumerable))] public static IQueryable TakeWhile(this IQueryable source, Expression> predicate) { @@ -972,7 +993,33 @@ public static TSource ElementAt(this IQueryable source, int in return source.Provider.Execute( Expression.Call( null, - CachedReflectionInfo.ElementAt_TSource_2(typeof(TSource)), + CachedReflectionInfo.ElementAt_Int32_TSource_2(typeof(TSource)), + source.Expression, Expression.Constant(index) + )); + } + + /// Returns the element at a specified index in a sequence. + /// An to return an element from. + /// The index of the element to retrieve, which is either from the start or the end. + /// The type of the elements of . + /// + /// is . + /// + /// + /// is outside the bounds of the sequence. + /// + /// The element at the specified position in the sequence. + [DynamicDependency("ElementAt`1", typeof(Enumerable))] + public static TSource ElementAt(this IQueryable source, Index index) + { + if (source == null) + throw Error.ArgumentNull(nameof(source)); + if (index.IsFromEnd && index.Value == 0) + throw Error.ArgumentOutOfRange(nameof(index)); + return source.Provider.Execute( + Expression.Call( + null, + CachedReflectionInfo.ElementAt_Index_TSource_2(typeof(TSource)), source.Expression, Expression.Constant(index) )); } @@ -985,7 +1032,30 @@ public static TSource ElementAt(this IQueryable source, int in return source.Provider.Execute( Expression.Call( null, - CachedReflectionInfo.ElementAtOrDefault_TSource_2(typeof(TSource)), + CachedReflectionInfo.ElementAtOrDefault_Int32_TSource_2(typeof(TSource)), + source.Expression, Expression.Constant(index) + )); + } + + /// Returns the element at a specified index in a sequence or a default value if the index is out of range. + /// An to return an element from. + /// The index of the element to retrieve, which is either from the start or the end. + /// The type of the elements of . + /// + /// is . + /// + /// + /// if index is outside the bounds of the sequence; otherwise, the element at the specified position in the sequence. + /// + [DynamicDependency("ElementAtOrDefault`1", typeof(Enumerable))] + public static TSource? ElementAtOrDefault(this IQueryable source, Index index) + { + if (source == null) + throw Error.ArgumentNull(nameof(source)); + return source.Provider.Execute( + Expression.Call( + null, + CachedReflectionInfo.ElementAtOrDefault_Index_TSource_2(typeof(TSource)), source.Expression, Expression.Constant(index) )); } diff --git a/src/libraries/System.Linq.Queryable/tests/ElementAtOrDefaultTests.cs b/src/libraries/System.Linq.Queryable/tests/ElementAtOrDefaultTests.cs index c86d69de260c9..f6bf5c47d2dfc 100644 --- a/src/libraries/System.Linq.Queryable/tests/ElementAtOrDefaultTests.cs +++ b/src/libraries/System.Linq.Queryable/tests/ElementAtOrDefaultTests.cs @@ -8,11 +8,19 @@ namespace System.Linq.Tests public class ElementAtOrDefaultTests : EnumerableBasedTests { [Fact] - public void IndexNegative() + public void IndexInvalid() { int?[] source = { 9, 8 }; Assert.Null(source.AsQueryable().ElementAtOrDefault(-1)); + Assert.Null(source.AsQueryable().ElementAtOrDefault(int.MinValue)); + Assert.Null(source.AsQueryable().ElementAtOrDefault(3)); + Assert.Null(source.AsQueryable().ElementAtOrDefault(int.MaxValue)); + + Assert.Null(source.AsQueryable().ElementAtOrDefault(^3)); + Assert.Null(source.AsQueryable().ElementAtOrDefault(^int.MaxValue)); + Assert.Null(source.AsQueryable().ElementAtOrDefault(new Index(3))); + Assert.Null(source.AsQueryable().ElementAtOrDefault(new Index(int.MaxValue))); } [Fact] @@ -20,7 +28,9 @@ public void IndexEqualsCount() { int[] source = { 1, 2, 3, 4 }; - Assert.Equal(default(int), source.AsQueryable().ElementAtOrDefault(source.Length)); + Assert.Equal(default, source.AsQueryable().ElementAtOrDefault(source.Length)); + Assert.Equal(default, source.AsQueryable().ElementAtOrDefault(new Index(source.Length))); + Assert.Equal(default, source.AsQueryable().ElementAtOrDefault(^0)); } [Fact] @@ -28,7 +38,9 @@ public void EmptyIndexZero() { int[] source = { }; - Assert.Equal(default(int), source.AsQueryable().ElementAtOrDefault(0)); + Assert.Equal(default, source.AsQueryable().ElementAtOrDefault(0)); + Assert.Equal(default, source.AsQueryable().ElementAtOrDefault(new Index(0))); + Assert.Equal(default, source.AsQueryable().ElementAtOrDefault(^0)); } [Fact] @@ -37,6 +49,8 @@ public void SingleElementIndexZero() int[] source = { -4 }; Assert.Equal(-4, source.ElementAtOrDefault(0)); + Assert.Equal(-4, source.ElementAtOrDefault(new Index(0))); + Assert.Equal(-4, source.ElementAtOrDefault(^1)); } [Fact] @@ -45,19 +59,29 @@ public void ManyElementsIndexTargetsLast() int[] source = { 9, 8, 0, -5, 10 }; Assert.Equal(10, source.AsQueryable().ElementAtOrDefault(source.Length - 1)); + Assert.Equal(10, source.AsQueryable().ElementAtOrDefault(new Index(source.Length - 1))); + Assert.Equal(10, source.AsQueryable().ElementAtOrDefault(^1)); } [Fact] public void NullSource() { AssertExtensions.Throws("source", () => ((IQueryable)null).ElementAtOrDefault(2)); + AssertExtensions.Throws("source", () => ((IQueryable)null).ElementAtOrDefault(new Index(2))); + AssertExtensions.Throws("source", () => ((IQueryable)null).ElementAtOrDefault(^2)); } [Fact] public void ElementAtOrDefault() { - var val = (new int[] { 0, 2, 1 }).AsQueryable().ElementAtOrDefault(1); - Assert.Equal(2, val); + var val1 = new[] { 0, 2, 1 }.AsQueryable().ElementAtOrDefault(1); + Assert.Equal(2, val1); + + var val2 = new[] { 0, 2, 1 }.AsQueryable().ElementAtOrDefault(new Index(1)); + Assert.Equal(2, val2); + + var val3 = new[] { 0, 2, 1 }.AsQueryable().ElementAtOrDefault(^2); + Assert.Equal(2, val3); } } } diff --git a/src/libraries/System.Linq.Queryable/tests/ElementAtTests.cs b/src/libraries/System.Linq.Queryable/tests/ElementAtTests.cs index c334438c86ab7..bc6662ea007aa 100644 --- a/src/libraries/System.Linq.Queryable/tests/ElementAtTests.cs +++ b/src/libraries/System.Linq.Queryable/tests/ElementAtTests.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; using Xunit; namespace System.Linq.Tests @@ -14,6 +13,7 @@ public void IndexNegative() int?[] source = { 9, 8 }; AssertExtensions.Throws("index", () => source.AsQueryable().ElementAt(-1)); + AssertExtensions.Throws("index", () => source.AsQueryable().ElementAt(^3)); } [Fact] @@ -22,6 +22,8 @@ public void IndexEqualsCount() int[] source = { 1, 2, 3, 4 }; AssertExtensions.Throws("index", () => source.AsQueryable().ElementAt(source.Length)); + AssertExtensions.Throws("index", () => source.AsQueryable().ElementAt(new Index(source.Length))); + AssertExtensions.Throws("index", () => source.AsQueryable().ElementAt(^0)); } [Fact] @@ -30,6 +32,8 @@ public void EmptyIndexZero() int[] source = { }; AssertExtensions.Throws("index", () => source.AsQueryable().ElementAt(0)); + AssertExtensions.Throws("index", () => source.AsQueryable().ElementAt(new Index(0))); + AssertExtensions.Throws("index", () => source.AsQueryable().ElementAt(^0)); } [Fact] @@ -38,6 +42,8 @@ public void SingleElementIndexZero() int[] source = { -4 }; Assert.Equal(-4, source.AsQueryable().ElementAt(0)); + Assert.Equal(-4, source.AsQueryable().ElementAt(new Index(0))); + Assert.Equal(-4, source.AsQueryable().ElementAt(^1)); } [Fact] @@ -46,19 +52,29 @@ public void ManyElementsIndexTargetsLast() int[] source = { 9, 8, 0, -5, 10 }; Assert.Equal(10, source.AsQueryable().ElementAt(source.Length - 1)); + Assert.Equal(10, source.AsQueryable().ElementAt(source.Length - 1)); + Assert.Equal(10, source.AsQueryable().ElementAt(^1)); } [Fact] public void NullSource() { AssertExtensions.Throws("source", () => ((IQueryable)null).ElementAt(2)); + AssertExtensions.Throws("source", () => ((IQueryable)null).ElementAt(new Index(2))); + AssertExtensions.Throws("source", () => ((IQueryable)null).ElementAt(^2)); } [Fact] public void ElementAt() { - var val = (new int[] { 0, 2, 1 }).AsQueryable().ElementAt(1); - Assert.Equal(2, val); + var val1 = new[] { 0, 2, 1 }.AsQueryable().ElementAt(1); + Assert.Equal(2, val1); + + var val2 = new[] { 0, 2, 1 }.AsQueryable().ElementAt(new Index(1)); + Assert.Equal(2, val2); + + var val3 = new[] { 0, 2, 1 }.AsQueryable().ElementAt(^2); + Assert.Equal(2, val3); } } } diff --git a/src/libraries/System.Linq.Queryable/tests/TakeTests.cs b/src/libraries/System.Linq.Queryable/tests/TakeTests.cs index ecafe37a51d83..2dd8a77cf6f6d 100644 --- a/src/libraries/System.Linq.Queryable/tests/TakeTests.cs +++ b/src/libraries/System.Linq.Queryable/tests/TakeTests.cs @@ -14,6 +14,10 @@ public void SourceNonEmptyTakeAllButOne() int[] expected = { 2, 5, 9 }; Assert.Equal(expected, source.AsQueryable().Take(3)); + Assert.Equal(expected, source.AsQueryable().Take(0..3)); + Assert.Equal(expected, source.AsQueryable().Take(^4..3)); + Assert.Equal(expected, source.AsQueryable().Take(0..^1)); + Assert.Equal(expected, source.AsQueryable().Take(^4..^1)); } [Fact] @@ -21,13 +25,41 @@ public void ThrowsOnNullSource() { IQueryable source = null; AssertExtensions.Throws("source", () => source.Take(5)); + AssertExtensions.Throws("source", () => source.Take(0..5)); + AssertExtensions.Throws("source", () => source.Take(^5..5)); + AssertExtensions.Throws("source", () => source.Take(0..^0)); + AssertExtensions.Throws("source", () => source.Take(^5..^0)); } [Fact] public void Take() { - var count = (new int[] { 0, 1, 2 }).AsQueryable().Take(2).Count(); - Assert.Equal(2, count); + var count1 = new[] { 0, 1, 2 }.AsQueryable().Take(2).Count(); + Assert.Equal(2, count1); + + var count2 = new[] { 0, 1, 2 }.AsQueryable().Take(0..2).Count(); + Assert.Equal(2, count2); + + var count3 = new[] { 0, 1, 2 }.AsQueryable().Take(^3..2).Count(); + Assert.Equal(2, count3); + + var count4 = new[] { 0, 1, 2 }.AsQueryable().Take(0..^1).Count(); + Assert.Equal(2, count4); + + var count5 = new[] { 0, 1, 2 }.AsQueryable().Take(^3..^1).Count(); + Assert.Equal(2, count5); + + var count6 = new[] { 0, 1, 2 }.AsQueryable().Take(1..3).Count(); + Assert.Equal(2, count6); + + var count7 = new[] { 0, 1, 2 }.AsQueryable().Take(^2..3).Count(); + Assert.Equal(2, count7); + + var count8 = new[] { 0, 1, 2 }.AsQueryable().Take(1..^0).Count(); + Assert.Equal(2, count8); + + var count9 = new[] { 0, 1, 2 }.AsQueryable().Take(^2..^0).Count(); + Assert.Equal(2, count9); } } } diff --git a/src/libraries/System.Linq.Queryable/tests/TrimCompatibilityTests.cs b/src/libraries/System.Linq.Queryable/tests/TrimCompatibilityTests.cs index 76d7e864ca9b4..3d02b20ae0ec1 100644 --- a/src/libraries/System.Linq.Queryable/tests/TrimCompatibilityTests.cs +++ b/src/libraries/System.Linq.Queryable/tests/TrimCompatibilityTests.cs @@ -61,7 +61,7 @@ public static void CachedReflectionInfoMethodsNoAnnotations() .Where(m => m.GetParameters().Length > 0); // If you are adding a new method to this class, ensure the method meets these requirements - Assert.Equal(108, methods.Count()); + Assert.Equal(111, methods.Count()); foreach (MethodInfo method in methods) { ParameterInfo[] parameters = method.GetParameters(); diff --git a/src/libraries/System.Linq/ref/System.Linq.cs b/src/libraries/System.Linq/ref/System.Linq.cs index f401b5ed47319..7a86417711aa7 100644 --- a/src/libraries/System.Linq/ref/System.Linq.cs +++ b/src/libraries/System.Linq/ref/System.Linq.cs @@ -52,7 +52,9 @@ public static System.Collections.Generic.IEnumerable< public static System.Collections.Generic.IEnumerable Distinct(this System.Collections.Generic.IEnumerable source) { throw null; } public static System.Collections.Generic.IEnumerable Distinct(this System.Collections.Generic.IEnumerable source, System.Collections.Generic.IEqualityComparer? comparer) { throw null; } public static TSource? ElementAtOrDefault(this System.Collections.Generic.IEnumerable source, int index) { throw null; } + public static TSource? ElementAtOrDefault(this System.Collections.Generic.IEnumerable source, System.Index index) { throw null; } public static TSource ElementAt(this System.Collections.Generic.IEnumerable source, int index) { throw null; } + public static TSource ElementAt(this System.Collections.Generic.IEnumerable source, System.Index index) { throw null; } public static System.Collections.Generic.IEnumerable Empty() { throw null; } public static System.Collections.Generic.IEnumerable Except(this System.Collections.Generic.IEnumerable first, System.Collections.Generic.IEnumerable second) { throw null; } public static System.Collections.Generic.IEnumerable Except(this System.Collections.Generic.IEnumerable first, System.Collections.Generic.IEnumerable second, System.Collections.Generic.IEqualityComparer? comparer) { throw null; } @@ -173,6 +175,7 @@ public static System.Collections.Generic.IEnumerable< public static System.Collections.Generic.IEnumerable TakeWhile(this System.Collections.Generic.IEnumerable source, System.Func predicate) { throw null; } public static System.Collections.Generic.IEnumerable TakeWhile(this System.Collections.Generic.IEnumerable source, System.Func predicate) { throw null; } public static System.Collections.Generic.IEnumerable Take(this System.Collections.Generic.IEnumerable source, int count) { throw null; } + public static System.Collections.Generic.IEnumerable Take(this System.Collections.Generic.IEnumerable source, System.Range range) { throw null; } public static System.Linq.IOrderedEnumerable ThenByDescending(this System.Linq.IOrderedEnumerable source, System.Func keySelector) { throw null; } public static System.Linq.IOrderedEnumerable ThenByDescending(this System.Linq.IOrderedEnumerable source, System.Func keySelector, System.Collections.Generic.IComparer? comparer) { throw null; } public static System.Linq.IOrderedEnumerable ThenBy(this System.Linq.IOrderedEnumerable source, System.Func keySelector) { throw null; } diff --git a/src/libraries/System.Linq/src/System/Linq/ElementAt.cs b/src/libraries/System.Linq/src/System/Linq/ElementAt.cs index fa1256a6f22ab..46d9399d36230 100644 --- a/src/libraries/System.Linq/src/System/Linq/ElementAt.cs +++ b/src/libraries/System.Linq/src/System/Linq/ElementAt.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; +using System.Diagnostics; using System.Diagnostics.CodeAnalysis; namespace System.Linq @@ -23,34 +24,54 @@ public static TSource ElementAt(this IEnumerable source, int i return element!; } } - else + else if (source is IList list) { - if (source is IList list) - { - return list[index]; - } - - if (index >= 0) - { - using (IEnumerator e = source.GetEnumerator()) - { - while (e.MoveNext()) - { - if (index == 0) - { - return e.Current; - } - - index--; - } - } - } + return list[index]; + } + else if (TryGetElement(source, index, out TSource? element)) + { + return element; } ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); return default; } + /// Returns the element at a specified index in a sequence. + /// An to return an element from. + /// The index of the element to retrieve, which is either from the start or the end. + /// The type of the elements of . + /// + /// is . + /// + /// is outside the bounds of the sequence. + /// + /// The element at the specified position in the sequence. + public static TSource ElementAt(this IEnumerable source, Index index) + { + if (source == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source); + } + + if (!index.IsFromEnd) + { + return source.ElementAt(index.Value); + } + + if (source.TryGetNonEnumeratedCount(out int count)) + { + return source.ElementAt(count - index.Value); + } + + if (!TryGetElementFromEnd(source, index.Value, out TSource? element)) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); + } + + return element; + } + public static TSource? ElementAtOrDefault(this IEnumerable source, int index) { if (source == null) @@ -63,33 +84,101 @@ public static TSource ElementAt(this IEnumerable source, int i return partition.TryGetElementAt(index, out bool _); } + if (source is IList list) + { + return index >= 0 && index < list.Count ? list[index] : default; + } + + TryGetElement(source, index, out TSource? element); + return element; + + } + + /// Returns the element at a specified index in a sequence or a default value if the index is out of range. + /// An to return an element from. + /// The index of the element to retrieve, which is either from the start or the end. + /// The type of the elements of . + /// + /// is . + /// + /// + /// if is outside the bounds of the sequence; otherwise, the element at the specified position in the sequence. + /// + public static TSource? ElementAtOrDefault(this IEnumerable source, Index index) + { + if (source == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source); + } + + if (!index.IsFromEnd) + { + return source.ElementAtOrDefault(index.Value); + } + + if (source.TryGetNonEnumeratedCount(out int count)) + { + return source.ElementAtOrDefault(count - index.Value); + } + + TryGetElementFromEnd(source, index.Value, out TSource? element); + return element; + } + + private static bool TryGetElement(IEnumerable source, int index, [MaybeNullWhen(false)] out TSource element) + { + Debug.Assert(source != null); + if (index >= 0) { - if (source is IList list) + using IEnumerator e = source.GetEnumerator(); + while (e.MoveNext()) { - if (index < list.Count) + if (index == 0) { - return list[index]; + element = e.Current; + return true; } + + index--; } - else + } + + element = default; + return false; + } + + private static bool TryGetElementFromEnd(IEnumerable source, int indexFromEnd, [MaybeNullWhen(false)] out TSource element) + { + Debug.Assert(source != null); + + if (indexFromEnd > 0) + { + using IEnumerator e = source.GetEnumerator(); + if (e.MoveNext()) { - using (IEnumerator e = source.GetEnumerator()) + Queue queue = new(); + queue.Enqueue(e.Current); + while (e.MoveNext()) { - while (e.MoveNext()) + if (queue.Count == indexFromEnd) { - if (index == 0) - { - return e.Current; - } - - index--; + queue.Dequeue(); } + + queue.Enqueue(e.Current); + } + + if (queue.Count == indexFromEnd) + { + element = queue.Dequeue(); + return true; } } } - return default; + element = default; + return false; } } } diff --git a/src/libraries/System.Linq/src/System/Linq/Take.cs b/src/libraries/System.Linq/src/System/Linq/Take.cs index 79ab4e81f00de..c6db5760a08a2 100644 --- a/src/libraries/System.Linq/src/System/Linq/Take.cs +++ b/src/libraries/System.Linq/src/System/Linq/Take.cs @@ -20,6 +20,158 @@ public static IEnumerable Take(this IEnumerable sourc TakeIterator(source, count); } + /// Returns a specified range of contiguous elements from a sequence. + /// The sequence to return elements from. + /// The range of elements to return, which has start and end indexes either from the start or the end. + /// The type of the elements of . + /// + /// is . + /// + /// An that contains the specified of elements from the sequence. + public static IEnumerable Take(this IEnumerable source, Range range) + { + if (source == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source); + } + + Index start = range.Start; + Index end = range.End; + bool isStartIndexFromEnd = start.IsFromEnd; + bool isEndIndexFromEnd = end.IsFromEnd; + int startIndex = start.Value; + int endIndex = end.Value; + Debug.Assert(startIndex >= 0); + Debug.Assert(endIndex >= 0); + + if (isStartIndexFromEnd) + { + if (startIndex == 0 || (isEndIndexFromEnd && endIndex >= startIndex)) + { + return Empty(); + } + } + else if (!isEndIndexFromEnd) + { + return startIndex >= endIndex + ? Empty() + : source.Skip(startIndex).Take(endIndex - startIndex); + } + + return TakeIterator(source, isStartIndexFromEnd, startIndex, isEndIndexFromEnd, endIndex); + } + + private static IEnumerable TakeIterator( + IEnumerable source, bool isStartIndexFromEnd, int startIndex, bool isEndIndexFromEnd, int endIndex) + { + Debug.Assert(source != null); + Debug.Assert(isStartIndexFromEnd + ? startIndex > 0 && (!isEndIndexFromEnd || startIndex > endIndex) + : startIndex >= 0 && (isEndIndexFromEnd || startIndex < endIndex)); + Debug.Assert(endIndex >= 0); + + using IEnumerator e = source.GetEnumerator(); + if (isStartIndexFromEnd) + { + if (!e.MoveNext()) + { + yield break; + } + + int index = 0; + Queue queue = new(); + queue.Enqueue(e.Current); + + while (e.MoveNext()) + { + checked + { + index++; + } + + if (queue.Count == startIndex) + { + queue.Dequeue(); + } + + queue.Enqueue(e.Current); + } + + int count = checked(index + 1); + Debug.Assert(queue.Count == Math.Min(count, startIndex)); + + startIndex = count - startIndex; + if (startIndex < 0) + { + startIndex = 0; + } + + if (isEndIndexFromEnd) + { + endIndex = count - endIndex; + } + else if (endIndex > count) + { + endIndex = count; + } + + Debug.Assert(endIndex - startIndex <= queue.Count); + for (int rangeIndex = startIndex; rangeIndex < endIndex; rangeIndex++) + { + yield return queue.Dequeue(); + } + } + else + { + int index = 0; + while (index <= startIndex) + { + if (!e.MoveNext()) + { + yield break; + } + + checked + { + index++; + } + } + + if (isEndIndexFromEnd) + { + if (endIndex > 0) + { + Queue queue = new(); + do + { + if (queue.Count == endIndex) + { + yield return queue.Dequeue(); + } + + queue.Enqueue(e.Current); + } while (e.MoveNext()); + } + else + { + do + { + yield return e.Current; + } while (e.MoveNext()); + } + } + else + { + Debug.Assert(index < endIndex); + yield return e.Current; + while (checked(++index) < endIndex && e.MoveNext()) + { + yield return e.Current; + } + } + } + } + public static IEnumerable TakeWhile(this IEnumerable source, Func predicate) { if (source == null) diff --git a/src/libraries/System.Linq/tests/ElementAtOrDefaultTests.cs b/src/libraries/System.Linq/tests/ElementAtOrDefaultTests.cs index 7d9d66b438420..a462be3e8cfc8 100644 --- a/src/libraries/System.Linq/tests/ElementAtOrDefaultTests.cs +++ b/src/libraries/System.Linq/tests/ElementAtOrDefaultTests.cs @@ -11,73 +11,404 @@ public class ElementAtOrDefaultTests : EnumerableTests [Fact] public void SameResultsRepeatCallsIntQuery() { - var q = from x in new[] { 9999, 0, 888, -1, 66, -777, 1, 2, -12345 } - where x > int.MinValue - select x; - - Assert.Equal(q.ElementAtOrDefault(3), q.ElementAtOrDefault(3)); + var q = Repeat(_ => from x in new[] { 9999, 0, 888, -1, 66, -777, 1, 2, -12345 } + where x > int.MinValue + select x, 3); + Assert.Equal(q[0].ElementAtOrDefault(3), q[0].ElementAtOrDefault(3)); + Assert.Equal(q[1].ElementAtOrDefault(new Index(3)), q[1].ElementAtOrDefault(new Index(3))); + Assert.Equal(q[2].ElementAtOrDefault(^6), q[2].ElementAtOrDefault(^6)); } [Fact] public void SameResultsRepeatCallsStringQuery() { - var q = from x in new[] { "!@#$%^", "C", "AAA", "", "Calling Twice", "SoS", string.Empty } - where !string.IsNullOrEmpty(x) - select x; - - Assert.Equal(q.ElementAtOrDefault(4), q.ElementAtOrDefault(4)); + var q = Repeat(_ => from x in new[] { "!@#$%^", "C", "AAA", "", "Calling Twice", "SoS", string.Empty } + where !string.IsNullOrEmpty(x) + select x, 3); + Assert.Equal(q[0].ElementAtOrDefault(4), q[0].ElementAtOrDefault(4)); + Assert.Equal(q[1].ElementAtOrDefault(new Index(4)), q[1].ElementAtOrDefault(new Index(4))); + Assert.Equal(q[2].ElementAtOrDefault(^2), q[2].ElementAtOrDefault(^2)); } public static IEnumerable TestData() { - yield return new object[] { NumberRangeGuaranteedNotCollectionType(9, 1), 0, 9 }; - yield return new object[] { NumberRangeGuaranteedNotCollectionType(9, 10), 9, 18 }; - yield return new object[] { NumberRangeGuaranteedNotCollectionType(-4, 10), 3, -1 }; + yield return new object[] { NumberRangeGuaranteedNotCollectionType(9, 1), 0, 1, 9 }; + yield return new object[] { NumberRangeGuaranteedNotCollectionType(9, 10), 9, 1, 18 }; + yield return new object[] { NumberRangeGuaranteedNotCollectionType(-4, 10), 3, 7, -1 }; - yield return new object[] { new int[] { 1, 2, 3, 4 }, 4, 0 }; - yield return new object[] { new int[0], 0, 0 }; - yield return new object[] { new int[] { -4 }, 0, -4 }; - yield return new object[] { new int[] { 9, 8, 0, -5, 10 }, 4, 10 }; + yield return new object[] { new int[] { 1, 2, 3, 4 }, 4, 0, 0 }; + yield return new object[] { new int[0], 0, 0, 0 }; + yield return new object[] { new int[] { -4 }, 0, 1, -4 }; + yield return new object[] { new int[] { 9, 8, 0, -5, 10 }, 4, 1, 10 }; - yield return new object[] { NumberRangeGuaranteedNotCollectionType(-4, 5), -1, 0 }; - yield return new object[] { NumberRangeGuaranteedNotCollectionType(5, 5), 5, 0 }; - yield return new object[] { NumberRangeGuaranteedNotCollectionType(0, 0), 0, 0 }; + yield return new object[] { NumberRangeGuaranteedNotCollectionType(-4, 5), -1, 6, 0 }; + yield return new object[] { NumberRangeGuaranteedNotCollectionType(5, 5), 5, 0, 0 }; + yield return new object[] { NumberRangeGuaranteedNotCollectionType(0, 0), 0, 0, 0 }; } [Theory] [MemberData(nameof(TestData))] - public void ElementAtOrDefault(IEnumerable source, int index, int expected) + public void ElementAtOrDefault(IEnumerable source, int index, int indexFromEnd, int expected) { Assert.Equal(expected, source.ElementAtOrDefault(index)); + + if (index >= 0) + { + Assert.Equal(expected, source.ElementAtOrDefault(new Index(index))); + } + + Assert.Equal(expected, source.ElementAtOrDefault(^indexFromEnd)); } [Theory] [MemberData(nameof(TestData))] - public void ElementAtOrDefaultRunOnce(IEnumerable source, int index, int expected) + public void ElementAtOrDefaultRunOnce(IEnumerable source, int index, int indexFromEnd, int expected) { Assert.Equal(expected, source.RunOnce().ElementAtOrDefault(index)); + + if (index >= 0) + { + Assert.Equal(expected, source.RunOnce().ElementAtOrDefault(new Index(index))); + } + + Assert.Equal(expected, source.RunOnce().ElementAtOrDefault(^indexFromEnd)); } [Fact] - public void NullableArray_NegativeIndex_ReturnsNull() + public void NullableArray_InvalidIndex_ReturnsNull() { int?[] source = { 9, 8 }; Assert.Null(source.ElementAtOrDefault(-1)); + Assert.Null(source.ElementAtOrDefault(3)); + Assert.Null(source.ElementAtOrDefault(int.MaxValue)); + Assert.Null(source.ElementAtOrDefault(int.MinValue)); + + Assert.Null(source.ElementAtOrDefault(^3)); + Assert.Null(source.ElementAtOrDefault(new Index(3))); + Assert.Null(source.ElementAtOrDefault(new Index(int.MaxValue))); + Assert.Null(source.ElementAtOrDefault(^int.MaxValue)); } [Fact] - public void NullableArray_ValidIndex_ReturnsCorrectObjecvt() + public void NullableArray_ValidIndex_ReturnsCorrectObject() { int?[] source = { 9, 8, null, -5, 10 }; Assert.Null(source.ElementAtOrDefault(2)); Assert.Equal(-5, source.ElementAtOrDefault(3)); + + Assert.Null(source.ElementAtOrDefault(new Index(2))); + Assert.Equal(-5, source.ElementAtOrDefault(new Index(3))); + + Assert.Null(source.ElementAtOrDefault(^3)); + Assert.Equal(-5, source.ElementAtOrDefault(^2)); } [Fact] public void NullSource_ThrowsArgumentNullException() { - AssertExtensions.Throws("source", () => ((IEnumerable)null).ElementAtOrDefault(2)); + Assert.Throws("source", () => ((IEnumerable)null).ElementAtOrDefault(2)); + Assert.Throws("source", () => ((IEnumerable)null).ElementAtOrDefault(new Index(2))); + Assert.Throws("source", () => ((IEnumerable)null).ElementAtOrDefault(^2)); + } + + [Fact] + public void MutableSource() + { + var source = new List() { 0, 1, 2, 3, 4 }; + Assert.Equal(2, source.ElementAtOrDefault(2)); + Assert.Equal(2, source.ElementAtOrDefault(new Index(2))); + Assert.Equal(2, source.ElementAtOrDefault(^3)); + + source.InsertRange(3, new[] { -1, -2 }); + source.RemoveAt(0); + Assert.Equal(-1, source.ElementAtOrDefault(2)); + Assert.Equal(-1, source.ElementAtOrDefault(new Index(2))); + Assert.Equal(-1, source.ElementAtOrDefault(^4)); + } + + [Fact] + public void MutableSourceNotList() + { + var source = new List() { 0, 1, 2, 3, 4 }; + var query1 = Repeat(_ => ForceNotCollection(source).Select(i => i), 3); + Assert.Equal(2, query1[0].ElementAtOrDefault(2)); + Assert.Equal(2, query1[1].ElementAtOrDefault(new Index(2))); + Assert.Equal(2, query1[2].ElementAtOrDefault(^3)); + + var query2 = Repeat(_ => ForceNotCollection(source).Select(i => i), 3); + source.InsertRange(3, new[] { -1, -2 }); + source.RemoveAt(0); + Assert.Equal(-1, query2[0].ElementAtOrDefault(2)); + Assert.Equal(-1, query2[1].ElementAtOrDefault(new Index(2))); + Assert.Equal(-1, query2[2].ElementAtOrDefault(^4)); + } + + [Fact] + public void EnumerateElements() + { + const int ElementCount = 10; + int state = -1; + int moveNextCallCount = 0; + Func> source = () => + { + state = -1; + moveNextCallCount = 0; + return new DelegateIterator( + moveNext: () => { moveNextCallCount++; return ++state < ElementCount; }, + current: () => state, + dispose: () => state = -1); + }; + + Assert.Equal(0, source().ElementAtOrDefault(0)); + Assert.Equal(1, moveNextCallCount); + Assert.Equal(0, source().ElementAtOrDefault(new Index(0))); + Assert.Equal(1, moveNextCallCount); + + Assert.Equal(5, source().ElementAtOrDefault(5)); + Assert.Equal(6, moveNextCallCount); + Assert.Equal(5, source().ElementAtOrDefault(new Index(5))); + Assert.Equal(6, moveNextCallCount); + + Assert.Equal(0, source().ElementAtOrDefault(^ElementCount)); + Assert.Equal(ElementCount + 1, moveNextCallCount); + Assert.Equal(5, source().ElementAtOrDefault(^5)); + Assert.Equal(ElementCount + 1, moveNextCallCount); + + Assert.Null(source().ElementAtOrDefault(ElementCount)); + Assert.Equal(ElementCount + 1, moveNextCallCount); + Assert.Null(source().ElementAtOrDefault(new Index(ElementCount))); + Assert.Equal(ElementCount + 1, moveNextCallCount); + Assert.Null(source().ElementAtOrDefault(^0)); + Assert.Equal(0, moveNextCallCount); + } + + [Fact] + public void NonEmptySource_Consistency() + { + int?[] source = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + + Assert.Equal(5, source.ElementAtOrDefault(5)); + Assert.Equal(5, source.ElementAtOrDefault(new Index(5))); + Assert.Equal(5, source.ElementAtOrDefault(^5)); + + Assert.Equal(0, source.ElementAtOrDefault(0)); + Assert.Equal(0, source.ElementAtOrDefault(new Index(0))); + Assert.Equal(0, source.ElementAtOrDefault(^10)); + + Assert.Equal(9, source.ElementAtOrDefault(9)); + Assert.Equal(9, source.ElementAtOrDefault(new Index(9))); + Assert.Equal(9, source.ElementAtOrDefault(^1)); + + Assert.Null(source.ElementAtOrDefault(-1)); + Assert.Null(source.ElementAtOrDefault(^11)); + + Assert.Null(source.ElementAtOrDefault(10)); + Assert.Null(source.ElementAtOrDefault(new Index(10))); + Assert.Null(source.ElementAtOrDefault(^0)); + + Assert.Null(source.ElementAtOrDefault(int.MinValue)); + Assert.Null(source.ElementAtOrDefault(^int.MaxValue)); + + Assert.Null(source.ElementAtOrDefault(int.MaxValue)); + Assert.Null(source.ElementAtOrDefault(new Index(int.MaxValue))); + } + + [Fact] + public void NonEmptySource_Consistency_NotList() + { + int?[] source = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + + Assert.Equal(5, ForceNotCollection(source).ElementAtOrDefault(5)); + Assert.Equal(5, ForceNotCollection(source).ElementAtOrDefault(new Index(5))); + Assert.Equal(5, ForceNotCollection(source).ElementAtOrDefault(^5)); + + Assert.Equal(0, ForceNotCollection(source).ElementAtOrDefault(0)); + Assert.Equal(0, ForceNotCollection(source).ElementAtOrDefault(new Index(0))); + Assert.Equal(0, ForceNotCollection(source).ElementAtOrDefault(^10)); + + Assert.Equal(9, ForceNotCollection(source).ElementAtOrDefault(9)); + Assert.Equal(9, ForceNotCollection(source).ElementAtOrDefault(new Index(9))); + Assert.Equal(9, ForceNotCollection(source).ElementAtOrDefault(^1)); + + Assert.Null(ForceNotCollection(source).ElementAtOrDefault(-1)); + Assert.Null(ForceNotCollection(source).ElementAtOrDefault(^11)); + + Assert.Null(ForceNotCollection(source).ElementAtOrDefault(10)); + Assert.Null(ForceNotCollection(source).ElementAtOrDefault(new Index(10))); + Assert.Null(ForceNotCollection(source).ElementAtOrDefault(^0)); + + const int ElementCount = 10; + int state = -1; + int moveNextCallCount = 0; + Func> getSource = () => + { + state = -1; + moveNextCallCount = 0; + return new DelegateIterator( + moveNext: () => { moveNextCallCount++; return ++state < ElementCount; }, + current: () => state, + dispose: () => state = -1); + }; + + Assert.Null(getSource().ElementAtOrDefault(10)); + Assert.Equal(ElementCount + 1, moveNextCallCount); + Assert.Null(getSource().ElementAtOrDefault(new Index(10))); + Assert.Equal(ElementCount + 1, moveNextCallCount); + Assert.Null(getSource().ElementAtOrDefault(^0)); + Assert.Equal(0, moveNextCallCount); + + Assert.Null(ForceNotCollection(source).ElementAtOrDefault(int.MinValue)); + Assert.Null(ForceNotCollection(source).ElementAtOrDefault(^int.MaxValue)); + + Assert.Null(ForceNotCollection(source).ElementAtOrDefault(int.MaxValue)); + Assert.Null(ForceNotCollection(source).ElementAtOrDefault(new Index(int.MaxValue))); + } + + [Fact] + public void NonEmptySource_Consistency_ListPartition() + { + int?[] source = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + + Assert.Equal(5, ListPartitionOrEmpty(source).ElementAtOrDefault(5)); + Assert.Equal(5, ListPartitionOrEmpty(source).ElementAtOrDefault(new Index(5))); + Assert.Equal(5, ListPartitionOrEmpty(source).ElementAtOrDefault(^5)); + + Assert.Equal(0, ListPartitionOrEmpty(source).ElementAtOrDefault(0)); + Assert.Equal(0, ListPartitionOrEmpty(source).ElementAtOrDefault(new Index(0))); + Assert.Equal(0, ListPartitionOrEmpty(source).ElementAtOrDefault(^10)); + + Assert.Equal(9, ListPartitionOrEmpty(source).ElementAtOrDefault(9)); + Assert.Equal(9, ListPartitionOrEmpty(source).ElementAtOrDefault(new Index(9))); + Assert.Equal(9, ListPartitionOrEmpty(source).ElementAtOrDefault(^1)); + + Assert.Null(ListPartitionOrEmpty(source).ElementAtOrDefault(-1)); + Assert.Null(ListPartitionOrEmpty(source).ElementAtOrDefault(^11)); + + Assert.Null(ListPartitionOrEmpty(source).ElementAtOrDefault(10)); + Assert.Null(ListPartitionOrEmpty(source).ElementAtOrDefault(new Index(10))); + Assert.Null(ListPartitionOrEmpty(source).ElementAtOrDefault(^0)); + + Assert.Null(ListPartitionOrEmpty(source).ElementAtOrDefault(int.MinValue)); + Assert.Null(ListPartitionOrEmpty(source).ElementAtOrDefault(^int.MaxValue)); + + Assert.Null(ListPartitionOrEmpty(source).ElementAtOrDefault(int.MaxValue)); + Assert.Null(ListPartitionOrEmpty(source).ElementAtOrDefault(new Index(int.MaxValue))); + } + + [Fact] + public void NonEmptySource_Consistency_EnumerablePartition() + { + int?[] source = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + + Assert.Equal(5, EnumerablePartitionOrEmpty(source).ElementAtOrDefault(5)); + Assert.Equal(5, EnumerablePartitionOrEmpty(source).ElementAtOrDefault(new Index(5))); + Assert.Equal(5, EnumerablePartitionOrEmpty(source).ElementAtOrDefault(^5)); + + Assert.Equal(0, EnumerablePartitionOrEmpty(source).ElementAtOrDefault(0)); + Assert.Equal(0, EnumerablePartitionOrEmpty(source).ElementAtOrDefault(new Index(0))); + Assert.Equal(0, EnumerablePartitionOrEmpty(source).ElementAtOrDefault(^10)); + + Assert.Equal(9, EnumerablePartitionOrEmpty(source).ElementAtOrDefault(9)); + Assert.Equal(9, EnumerablePartitionOrEmpty(source).ElementAtOrDefault(new Index(9))); + Assert.Equal(9, EnumerablePartitionOrEmpty(source).ElementAtOrDefault(^1)); + + Assert.Null(EnumerablePartitionOrEmpty(source).ElementAtOrDefault(-1)); + Assert.Null(EnumerablePartitionOrEmpty(source).ElementAtOrDefault(^11)); + + Assert.Null(EnumerablePartitionOrEmpty(source).ElementAtOrDefault(10)); + Assert.Null(EnumerablePartitionOrEmpty(source).ElementAtOrDefault(new Index(10))); + Assert.Null(EnumerablePartitionOrEmpty(source).ElementAtOrDefault(^0)); + + Assert.Null(EnumerablePartitionOrEmpty(source).ElementAtOrDefault(int.MinValue)); + Assert.Null(EnumerablePartitionOrEmpty(source).ElementAtOrDefault(^int.MaxValue)); + + Assert.Null(EnumerablePartitionOrEmpty(source).ElementAtOrDefault(int.MaxValue)); + Assert.Null(EnumerablePartitionOrEmpty(source).ElementAtOrDefault(new Index(int.MaxValue))); + } + + [Fact] + public void EmptySource_Consistency() + { + int?[] source = { }; + + Assert.Null(source.ElementAtOrDefault(1)); + Assert.Null(source.ElementAtOrDefault(-1)); + Assert.Null(source.ElementAtOrDefault(new Index(1))); + Assert.Null(source.ElementAtOrDefault(^1)); + + Assert.Null(source.ElementAtOrDefault(0)); + Assert.Null(source.ElementAtOrDefault(new Index(0))); + Assert.Null(source.ElementAtOrDefault(^0)); + + Assert.Null(source.ElementAtOrDefault(int.MinValue)); + Assert.Null(source.ElementAtOrDefault(^int.MaxValue)); + + Assert.Null(source.ElementAtOrDefault(int.MaxValue)); + Assert.Null(source.ElementAtOrDefault(new Index(int.MaxValue))); + } + + [Fact] + public void EmptySource_Consistency_NotList() + { + int?[] source = { }; + + Assert.Null(ForceNotCollection(source).ElementAtOrDefault(1)); + Assert.Null(ForceNotCollection(source).ElementAtOrDefault(-1)); + Assert.Null(ForceNotCollection(source).ElementAtOrDefault(new Index(1))); + Assert.Null(ForceNotCollection(source).ElementAtOrDefault(^1)); + + Assert.Null(ForceNotCollection(source).ElementAtOrDefault(0)); + Assert.Null(ForceNotCollection(source).ElementAtOrDefault(new Index(0))); + Assert.Null(ForceNotCollection(source).ElementAtOrDefault(^0)); + + Assert.Null(ForceNotCollection(source).ElementAtOrDefault(int.MinValue)); + Assert.Null(ForceNotCollection(source).ElementAtOrDefault(^int.MaxValue)); + + Assert.Null(ForceNotCollection(source).ElementAtOrDefault(int.MaxValue)); + Assert.Null(ForceNotCollection(source).ElementAtOrDefault(new Index(int.MaxValue))); + } + + [Fact] + public void EmptySource_Consistency_ListPartition() + { + int?[] source = { }; + + Assert.Null(ListPartitionOrEmpty(source).ElementAtOrDefault(1)); + Assert.Null(ListPartitionOrEmpty(source).ElementAtOrDefault(-1)); + Assert.Null(ListPartitionOrEmpty(source).ElementAtOrDefault(new Index(1))); + Assert.Null(ListPartitionOrEmpty(source).ElementAtOrDefault(^1)); + + Assert.Null(ListPartitionOrEmpty(source).ElementAtOrDefault(0)); + Assert.Null(ListPartitionOrEmpty(source).ElementAtOrDefault(new Index(0))); + Assert.Null(ListPartitionOrEmpty(source).ElementAtOrDefault(^0)); + + Assert.Null(ListPartitionOrEmpty(source).ElementAtOrDefault(int.MinValue)); + Assert.Null(ListPartitionOrEmpty(source).ElementAtOrDefault(^int.MaxValue)); + + Assert.Null(ListPartitionOrEmpty(source).ElementAtOrDefault(int.MaxValue)); + Assert.Null(ListPartitionOrEmpty(source).ElementAtOrDefault(new Index(int.MaxValue))); + } + + [Fact] + public void EmptySource_Consistency_EnumerablePartition() + { + int?[] source = { }; + + Assert.Null(EnumerablePartitionOrEmpty(source).ElementAtOrDefault(1)); + Assert.Null(EnumerablePartitionOrEmpty(source).ElementAtOrDefault(-1)); + Assert.Null(EnumerablePartitionOrEmpty(source).ElementAtOrDefault(new Index(1))); + Assert.Null(EnumerablePartitionOrEmpty(source).ElementAtOrDefault(^1)); + + Assert.Null(EnumerablePartitionOrEmpty(source).ElementAtOrDefault(0)); + Assert.Null(EnumerablePartitionOrEmpty(source).ElementAtOrDefault(new Index(0))); + Assert.Null(EnumerablePartitionOrEmpty(source).ElementAtOrDefault(^0)); + + Assert.Null(EnumerablePartitionOrEmpty(source).ElementAtOrDefault(int.MinValue)); + Assert.Null(EnumerablePartitionOrEmpty(source).ElementAtOrDefault(^int.MaxValue)); + + Assert.Null(EnumerablePartitionOrEmpty(source).ElementAtOrDefault(int.MaxValue)); + Assert.Null(EnumerablePartitionOrEmpty(source).ElementAtOrDefault(new Index(int.MaxValue))); } } } diff --git a/src/libraries/System.Linq/tests/ElementAtTests.cs b/src/libraries/System.Linq/tests/ElementAtTests.cs index 0b78c1ac6fbe9..8644a7df0d1e9 100644 --- a/src/libraries/System.Linq/tests/ElementAtTests.cs +++ b/src/libraries/System.Linq/tests/ElementAtTests.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; +using System.Collections.Immutable; using Xunit; namespace System.Linq.Tests @@ -11,58 +12,88 @@ public class ElementAtTests : EnumerableTests [Fact] public void SameResultsRepeatCallsIntQuery() { - var q = from x in new[] { 9999, 0, 888, -1, 66, -777, 1, 2, -12345 } - where x > int.MinValue - select x; - - Assert.Equal(q.ElementAt(3), q.ElementAt(3)); + var q = Repeat(_ => from x in new[] { 9999, 0, 888, -1, 66, -777, 1, 2, -12345 } + where x > int.MinValue + select x, 3); + Assert.Equal(q[0].ElementAt(3), q[0].ElementAt(3)); + Assert.Equal(q[1].ElementAt(new Index(3)), q[1].ElementAt(new Index(3))); + Assert.Equal(q[2].ElementAt(^6), q[2].ElementAt(^6)); } [Fact] public void SameResultsRepeatCallsStringQuery() { - var q = from x in new[] { "!@#$%^", "C", "AAA", "", "Calling Twice", "SoS", string.Empty } - where !string.IsNullOrEmpty(x) - select x; - - Assert.Equal(q.ElementAt(4), q.ElementAt(4)); + var q = Repeat(_ => from x in new[] { "!@#$%^", "C", "AAA", "", "Calling Twice", "SoS", string.Empty } + where !string.IsNullOrEmpty(x) + select x, 3); + Assert.Equal(q[0].ElementAt(4), q[0].ElementAt(4)); + Assert.Equal(q[1].ElementAt(new Index(4)), q[1].ElementAt(new Index(4))); + Assert.Equal(q[2].ElementAt(^2), q[2].ElementAt(^2)); } public static IEnumerable TestData() { - yield return new object[] { NumberRangeGuaranteedNotCollectionType(9, 1), 0, 9 }; - yield return new object[] { NumberRangeGuaranteedNotCollectionType(9, 10), 9, 18 }; - yield return new object[] { NumberRangeGuaranteedNotCollectionType(-4, 10), 3, -1 }; + yield return new object[] { NumberRangeGuaranteedNotCollectionType(9, 1), 0, 1, 9 }; + yield return new object[] { NumberRangeGuaranteedNotCollectionType(9, 10), 9, 1, 18 }; + yield return new object[] { NumberRangeGuaranteedNotCollectionType(-4, 10), 3, 7, -1 }; - yield return new object[] { new int[] { -4 }, 0, -4 }; - yield return new object[] { new int[] { 9, 8, 0, -5, 10 }, 4, 10 }; + yield return new object[] { new int[] { -4 }, 0, 1, -4 }; + yield return new object[] { new int[] { 9, 8, 0, -5, 10 }, 4, 1, 10 }; } [Theory] [MemberData(nameof(TestData))] - public void ElementAt(IEnumerable source, int index, int expected) + public void ElementAt(IEnumerable source, int index, int indexFromEnd, int expected) { Assert.Equal(expected, source.ElementAt(index)); + Assert.Equal(expected, source.ElementAt(new Index(index))); + Assert.Equal(expected, source.ElementAt(^indexFromEnd)); } [Theory] [MemberData(nameof(TestData))] - public void ElementAtRunOnce(IEnumerable source, int index, int expected) + public void ElementAtRunOnce(IEnumerable source, int index, int indexFromEnd, int expected) { Assert.Equal(expected, source.RunOnce().ElementAt(index)); + Assert.Equal(expected, source.RunOnce().ElementAt(new Index(index))); + Assert.Equal(expected, source.RunOnce().ElementAt(^indexFromEnd)); } [Fact] public void InvalidIndex_ThrowsArgumentOutOfRangeException() { - AssertExtensions.Throws("index", () => new int?[] { 9, 8 }.ElementAt(-1)); - AssertExtensions.Throws("index", () => new int[] { 1, 2, 3, 4 }.ElementAt(4)); - AssertExtensions.Throws("index", () => new int[0].ElementAt(0)); + Assert.Throws("index", () => new int?[] { 9, 8 }.ElementAt(-1)); + Assert.Throws("index", () => new int?[] { 9, 8 }.ElementAt(^3)); + Assert.Throws("index", () => new int?[] { 9, 8 }.ElementAt(int.MaxValue)); + Assert.Throws("index", () => new int?[] { 9, 8 }.ElementAt(int.MinValue)); + Assert.Throws("index", () => new int?[] { 9, 8 }.ElementAt(new Index(int.MaxValue))); + Assert.Throws("index", () => new int?[] { 9, 8 }.ElementAt(^int.MaxValue)); + + Assert.Throws("index", () => new int[] { 1, 2, 3, 4 }.ElementAt(4)); + Assert.Throws("index", () => new int[] { 1, 2, 3, 4 }.ElementAt(new Index(4))); + Assert.Throws("index", () => new int[] { 1, 2, 3, 4 }.ElementAt(^0)); + Assert.Throws("index", () => new int[] { 1, 2, 3, 4 }.ElementAt(^5)); + + Assert.Throws("index", () => new int[0].ElementAt(0)); + Assert.Throws("index", () => new int[0].ElementAt(new Index(0))); + Assert.Throws("index", () => new int[0].ElementAt(^0)); + Assert.Throws("index", () => new int[0].ElementAt(^1)); + + Assert.Throws("index", () => NumberRangeGuaranteedNotCollectionType(-4, 5).ElementAt(-1)); + Assert.Throws("index", () => NumberRangeGuaranteedNotCollectionType(-4, 5).ElementAt(int.MinValue)); + Assert.Throws("index", () => NumberRangeGuaranteedNotCollectionType(-4, 5).ElementAt(int.MaxValue)); + Assert.Throws("index", () => NumberRangeGuaranteedNotCollectionType(-4, 5).ElementAt(^6)); + Assert.Throws("index", () => NumberRangeGuaranteedNotCollectionType(-4, 5).ElementAt(new Index(int.MaxValue))); + Assert.Throws("index", () => NumberRangeGuaranteedNotCollectionType(-4, 5).ElementAt(^int.MaxValue)); - AssertExtensions.Throws("index", () => NumberRangeGuaranteedNotCollectionType(-4, 5).ElementAt(-1)); - AssertExtensions.Throws("index", () => NumberRangeGuaranteedNotCollectionType(5, 5).ElementAt(5)); - AssertExtensions.Throws("index", () => NumberRangeGuaranteedNotCollectionType(0, 0).ElementAt(0)); + Assert.Throws("index", () => NumberRangeGuaranteedNotCollectionType(5, 5).ElementAt(5)); + Assert.Throws("index", () => NumberRangeGuaranteedNotCollectionType(5, 5).ElementAt(new Index(5))); + Assert.Throws("index", () => NumberRangeGuaranteedNotCollectionType(5, 5).ElementAt(^0)); + Assert.Throws("index", () => NumberRangeGuaranteedNotCollectionType(0, 0).ElementAt(0)); + Assert.Throws("index", () => NumberRangeGuaranteedNotCollectionType(0, 0).ElementAt(new Index(0))); + Assert.Throws("index", () => NumberRangeGuaranteedNotCollectionType(0, 0).ElementAt(^0)); + Assert.Throws("index", () => NumberRangeGuaranteedNotCollectionType(0, 0).ElementAt(^1)); } [Fact] @@ -72,12 +103,444 @@ public void NullableArray_ValidIndex_ReturnsCorrectObject() Assert.Null(source.ElementAt(2)); Assert.Equal(-5, source.ElementAt(3)); + + Assert.Null(source.ElementAt(new Index(2))); + Assert.Equal(-5, source.ElementAt(new Index(3))); + + Assert.Null(source.ElementAt(^3)); + Assert.Equal(-5, source.ElementAt(^2)); } [Fact] public void NullSource_ThrowsArgumentNullException() { - AssertExtensions.Throws("source", () => ((IEnumerable)null).ElementAt(2)); + Assert.Throws("source", () => ((IEnumerable)null).ElementAt(2)); + Assert.Throws("source", () => ((IEnumerable)null).ElementAt(new Index(2))); + Assert.Throws("source", () => ((IEnumerable)null).ElementAt(^2)); + } + + [Fact] + public void MutableSource() + { + var source = new List() { 0, 1, 2, 3, 4 }; + Assert.Equal(2, source.ElementAt(2)); + Assert.Equal(2, source.ElementAt(new Index(2))); + Assert.Equal(2, source.ElementAt(^3)); + + source.InsertRange(3, new[] { -1, -2 }); + source.RemoveAt(0); + Assert.Equal(-1, source.ElementAt(2)); + Assert.Equal(-1, source.ElementAt(new Index(2))); + Assert.Equal(-1, source.ElementAt(^4)); + } + + [Fact] + public void MutableSourceNotList() + { + var source = new List() { 0, 1, 2, 3, 4 }; + var query1 = Repeat(_ => ForceNotCollection(source).Select(i => i), 3); + Assert.Equal(2, query1[0].ElementAt(2)); + Assert.Equal(2, query1[1].ElementAt(new Index(2))); + Assert.Equal(2, query1[2].ElementAt(^3)); + + var query2 = Repeat(_ => ForceNotCollection(source).Select(i => i), 3); + source.InsertRange(3, new[] { -1, -2 }); + source.RemoveAt(0); + Assert.Equal(-1, query2[0].ElementAt(2)); + Assert.Equal(-1, query2[1].ElementAt(new Index(2))); + Assert.Equal(-1, query2[2].ElementAt(^4)); + } + + [Fact] + public void EnumerateElements() + { + const int ElementCount = 10; + int state = -1; + int moveNextCallCount = 0; + Func> source = () => + { + state = -1; + moveNextCallCount = 0; + return new DelegateIterator( + moveNext: () => { moveNextCallCount++; return ++state < ElementCount; }, + current: () => state, + dispose: () => state = -1); + }; + + Assert.Equal(0, source().ElementAt(0)); + Assert.Equal(1, moveNextCallCount); + Assert.Equal(0, source().ElementAt(new Index(0))); + Assert.Equal(1, moveNextCallCount); + + Assert.Equal(5, source().ElementAt(5)); + Assert.Equal(6, moveNextCallCount); + Assert.Equal(5, source().ElementAt(new Index(5))); + Assert.Equal(6, moveNextCallCount); + + Assert.Equal(0, source().ElementAt(^ElementCount)); + Assert.Equal(ElementCount + 1, moveNextCallCount); + Assert.Equal(5, source().ElementAt(^5)); + Assert.Equal(ElementCount + 1, moveNextCallCount); + + Assert.Throws("index", () => source().ElementAt(ElementCount)); + Assert.Equal(ElementCount + 1, moveNextCallCount); + Assert.Throws("index", () => source().ElementAt(new Index(ElementCount))); + Assert.Equal(ElementCount + 1, moveNextCallCount); + Assert.Throws("index", () => source().ElementAt(^0)); + Assert.Equal(0, moveNextCallCount); + } + + [Fact] + public void NonEmptySource_Consistency() + { + int[] source = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + + Assert.Equal(5, source.ElementAt(5)); + Assert.Equal(5, source.ElementAt(new Index(5))); + Assert.Equal(5, source.ElementAt(^5)); + + Assert.Equal(0, source.ElementAt(0)); + Assert.Equal(0, source.ElementAt(new Index(0))); + Assert.Equal(0, source.ElementAt(^10)); + + Assert.Equal(9, source.ElementAt(9)); + Assert.Equal(9, source.ElementAt(new Index(9))); + Assert.Equal(9, source.ElementAt(^1)); + + Assert.Throws("index", () => source.ElementAt(-1)); + Assert.Throws("index", () => source.ElementAt(^11)); + + Assert.Throws("index", () => source.ElementAt(10)); + Assert.Throws("index", () => source.ElementAt(new Index(10))); + Assert.Throws("index", () => source.ElementAt(^0)); + + Assert.Throws("index", () => source.ElementAt(int.MinValue)); + Assert.Throws("index", () => source.ElementAt(^int.MaxValue)); + + Assert.Throws("index", () => source.ElementAt(int.MaxValue)); + Assert.Throws("index", () => source.ElementAt(new Index(int.MaxValue))); + } + + [Fact] + public void NonEmptySource_Consistency_ThrowsIListIndexerException() + { + int[] source = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + Assert.Throws("index", () => source.ElementAt(-1)); + Assert.Throws("index", () => source.ElementAt(^11)); + // ImmutableArray implements IList. ElementAt calls ImmutableArray's indexer, which throws IndexOutOfRangeException instead of ArgumentOutOfRangeException. + Assert.Throws(() => ImmutableArray.Create(source).ElementAt(-1)); + Assert.Throws(() => ImmutableArray.Create(source).ElementAt(^11)); + + Assert.Throws("index", () => source.ElementAt(10)); + Assert.Throws("index", () => source.ElementAt(new Index(10))); + Assert.Throws("index", () => source.ElementAt(^0)); + Assert.Throws(() => ImmutableArray.Create(source).ElementAt(10)); + Assert.Throws(() => ImmutableArray.Create(source).ElementAt(new Index(10))); + Assert.Throws(() => ImmutableArray.Create(source).ElementAt(^0)); + } + + [Fact] + public void NonEmptySource_Consistency_NotList() + { + int[] source = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + + Assert.Equal(5, ForceNotCollection(source).ElementAt(5)); + Assert.Equal(5, ForceNotCollection(source).ElementAt(new Index(5))); + Assert.Equal(5, ForceNotCollection(source).ElementAt(^5)); + + Assert.Equal(0, ForceNotCollection(source).ElementAt(0)); + Assert.Equal(0, ForceNotCollection(source).ElementAt(new Index(0))); + Assert.Equal(0, ForceNotCollection(source).ElementAt(^10)); + + Assert.Equal(9, ForceNotCollection(source).ElementAt(9)); + Assert.Equal(9, ForceNotCollection(source).ElementAt(new Index(9))); + Assert.Equal(9, ForceNotCollection(source).ElementAt(^1)); + + Assert.Throws("index", () => ForceNotCollection(source).ElementAt(-1)); + Assert.Throws("index", () => ForceNotCollection(source).ElementAt(^11)); + + Assert.Throws("index", () => ForceNotCollection(source).ElementAt(10)); + Assert.Throws("index", () => ForceNotCollection(source).ElementAt(new Index(10))); + Assert.Throws("index", () => ForceNotCollection(source).ElementAt(^0)); + + + + Assert.Throws("index", () => ForceNotCollection(source).ElementAt(int.MinValue)); + Assert.Throws("index", () => ForceNotCollection(source).ElementAt(^int.MaxValue)); + + Assert.Throws("index", () => ForceNotCollection(source).ElementAt(int.MaxValue)); + Assert.Throws("index", () => ForceNotCollection(source).ElementAt(new Index(int.MaxValue))); + } + + [Fact] + public void NonEmptySource_Consistency_ListPartition() + { + int[] source = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + + Assert.Equal(5, ListPartitionOrEmpty(source).ElementAt(5)); + Assert.Equal(5, ListPartitionOrEmpty(source).ElementAt(new Index(5))); + Assert.Equal(5, ListPartitionOrEmpty(source).ElementAt(^5)); + + Assert.Equal(0, ListPartitionOrEmpty(source).ElementAt(0)); + Assert.Equal(0, ListPartitionOrEmpty(source).ElementAt(new Index(0))); + Assert.Equal(0, ListPartitionOrEmpty(source).ElementAt(^10)); + + Assert.Equal(9, ListPartitionOrEmpty(source).ElementAt(9)); + Assert.Equal(9, ListPartitionOrEmpty(source).ElementAt(new Index(9))); + Assert.Equal(9, ListPartitionOrEmpty(source).ElementAt(^1)); + + Assert.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(-1)); + Assert.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(^11)); + + Assert.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(10)); + Assert.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(new Index(10))); + Assert.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(^0)); + + Assert.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(int.MinValue)); + Assert.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(^int.MaxValue)); + + Assert.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(int.MaxValue)); + Assert.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(new Index(int.MaxValue))); + } + + [Fact] + public void NonEmptySource_Consistency_EnumerablePartition() + { + int[] source = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + + Assert.Equal(5, EnumerablePartitionOrEmpty(source).ElementAt(5)); + Assert.Equal(5, EnumerablePartitionOrEmpty(source).ElementAt(new Index(5))); + Assert.Equal(5, EnumerablePartitionOrEmpty(source).ElementAt(^5)); + + Assert.Equal(0, EnumerablePartitionOrEmpty(source).ElementAt(0)); + Assert.Equal(0, EnumerablePartitionOrEmpty(source).ElementAt(new Index(0))); + Assert.Equal(0, EnumerablePartitionOrEmpty(source).ElementAt(^10)); + + Assert.Equal(9, EnumerablePartitionOrEmpty(source).ElementAt(9)); + Assert.Equal(9, EnumerablePartitionOrEmpty(source).ElementAt(new Index(9))); + Assert.Equal(9, EnumerablePartitionOrEmpty(source).ElementAt(^1)); + + Assert.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(-1)); + Assert.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(^11)); + + Assert.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(10)); + Assert.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(new Index(10))); + Assert.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(^0)); + + Assert.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(int.MinValue)); + Assert.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(^int.MaxValue)); + + Assert.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(int.MaxValue)); + Assert.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(new Index(int.MaxValue))); + } + + [Fact] + public void NonEmptySource_Consistency_Collection() + { + int[] source = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + + Assert.Equal(5, new TestCollection(source).ElementAt(5)); + Assert.Equal(5, new TestCollection(source).ElementAt(new Index(5))); + Assert.Equal(5, new TestCollection(source).ElementAt(^5)); + + Assert.Equal(0, new TestCollection(source).ElementAt(0)); + Assert.Equal(0, new TestCollection(source).ElementAt(new Index(0))); + Assert.Equal(0, new TestCollection(source).ElementAt(^10)); + + Assert.Equal(9, new TestCollection(source).ElementAt(9)); + Assert.Equal(9, new TestCollection(source).ElementAt(new Index(9))); + Assert.Equal(9, new TestCollection(source).ElementAt(^1)); + + Assert.Throws("index", () => new TestCollection(source).ElementAt(-1)); + Assert.Throws("index", () => new TestCollection(source).ElementAt(^11)); + + Assert.Throws("index", () => new TestCollection(source).ElementAt(10)); + Assert.Throws("index", () => new TestCollection(source).ElementAt(new Index(10))); + Assert.Throws("index", () => new TestCollection(source).ElementAt(^0)); + + Assert.Throws("index", () => new TestCollection(source).ElementAt(int.MinValue)); + Assert.Throws("index", () => new TestCollection(source).ElementAt(^int.MaxValue)); + + Assert.Throws("index", () => new TestCollection(source).ElementAt(int.MaxValue)); + Assert.Throws("index", () => new TestCollection(source).ElementAt(new Index(int.MaxValue))); + } + + [Fact] + public void NonEmptySource_Consistency_NonGenericCollection() + { + int[] source = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + + Assert.Equal(5, new TestNonGenericCollection(source.ToArray()).ElementAt(5)); + Assert.Equal(5, new TestNonGenericCollection(source.ToArray()).ElementAt(new Index(5))); + Assert.Equal(5, new TestNonGenericCollection(source.ToArray()).ElementAt(^5)); + + Assert.Equal(0, new TestNonGenericCollection(source.ToArray()).ElementAt(0)); + Assert.Equal(0, new TestNonGenericCollection(source.ToArray()).ElementAt(new Index(0))); + Assert.Equal(0, new TestNonGenericCollection(source.ToArray()).ElementAt(^10)); + + Assert.Equal(9, new TestNonGenericCollection(source.ToArray()).ElementAt(9)); + Assert.Equal(9, new TestNonGenericCollection(source.ToArray()).ElementAt(new Index(9))); + Assert.Equal(9, new TestNonGenericCollection(source.ToArray()).ElementAt(^1)); + + Assert.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(-1)); + Assert.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(^11)); + + Assert.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(10)); + Assert.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(new Index(10))); + Assert.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(^0)); + + Assert.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(int.MinValue)); + Assert.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(^int.MaxValue)); + + Assert.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(int.MaxValue)); + Assert.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(new Index(int.MaxValue))); + } + + [Fact] + public void EmptySource_Consistency() + { + int[] source = { }; + + Assert.Throws("index", () => source.ElementAt(1)); + Assert.Throws("index", () => source.ElementAt(-1)); + Assert.Throws("index", () => source.ElementAt(new Index(1))); + Assert.Throws("index", () => source.ElementAt(^1)); + + Assert.Throws("index", () => source.ElementAt(0)); + Assert.Throws("index", () => source.ElementAt(new Index(0))); + Assert.Throws("index", () => source.ElementAt(^0)); + + Assert.Throws("index", () => source.ElementAt(int.MinValue)); + Assert.Throws("index", () => source.ElementAt(^int.MaxValue)); + + Assert.Throws("index", () => source.ElementAt(int.MaxValue)); + Assert.Throws("index", () => source.ElementAt(new Index(int.MaxValue))); + } + + [Fact] + public void EmptySource_Consistency_ThrowsIListIndexerException() + { + int[] source = { }; + Assert.Throws("index", () => source.ElementAt(-1)); + Assert.Throws("index", () => source.ElementAt(^1)); + // ImmutableArray implements IList. ElementAt calls ImmutableArray's indexer, which throws IndexOutOfRangeException instead of ArgumentOutOfRangeException. + Assert.Throws(() => ImmutableArray.Create(source).ElementAt(-1)); + Assert.Throws(() => ImmutableArray.Create(source).ElementAt(^1)); + + Assert.Throws("index", () => source.ElementAt(0)); + Assert.Throws("index", () => source.ElementAt(^0)); + Assert.Throws(() => ImmutableArray.Create(source).ElementAt(0)); + Assert.Throws(() => ImmutableArray.Create(source).ElementAt(^0)); + + Assert.Throws("index", () => source.ElementAt(1)); + Assert.Throws("index", () => source.ElementAt(new Index(1))); + Assert.Throws(() => ImmutableArray.Create(source).ElementAt(1)); + Assert.Throws(() => ImmutableArray.Create(source).ElementAt(new Index(1))); + } + + [Fact] + public void EmptySource_Consistency_NotList() + { + int[] source = { }; + + Assert.Throws("index", () => ForceNotCollection(source).ElementAt(1)); + Assert.Throws("index", () => ForceNotCollection(source).ElementAt(-1)); + Assert.Throws("index", () => ForceNotCollection(source).ElementAt(new Index(1))); + Assert.Throws("index", () => ForceNotCollection(source).ElementAt(^1)); + + Assert.Throws("index", () => ForceNotCollection(source).ElementAt(0)); + Assert.Throws("index", () => ForceNotCollection(source).ElementAt(new Index(0))); + Assert.Throws("index", () => ForceNotCollection(source).ElementAt(^0)); + + Assert.Throws("index", () => ForceNotCollection(source).ElementAt(int.MinValue)); + Assert.Throws("index", () => ForceNotCollection(source).ElementAt(^int.MaxValue)); + + Assert.Throws("index", () => ForceNotCollection(source).ElementAt(int.MaxValue)); + Assert.Throws("index", () => ForceNotCollection(source).ElementAt(new Index(int.MaxValue))); + } + + [Fact] + public void EmptySource_Consistency_ListPartition() + { + int[] source = { }; + + Assert.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(1)); + Assert.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(-1)); + Assert.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(new Index(1))); + Assert.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(^1)); + + Assert.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(0)); + Assert.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(new Index(0))); + Assert.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(^0)); + + Assert.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(int.MinValue)); + Assert.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(^int.MaxValue)); + + Assert.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(int.MaxValue)); + Assert.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(new Index(int.MaxValue))); + } + + [Fact] + public void EmptySource_Consistency_EnumerablePartition() + { + int[] source = { }; + + Assert.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(1)); + Assert.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(-1)); + Assert.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(new Index(1))); + Assert.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(^1)); + + Assert.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(0)); + Assert.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(new Index(0))); + Assert.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(^0)); + + Assert.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(int.MinValue)); + Assert.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(^int.MaxValue)); + + Assert.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(int.MaxValue)); + Assert.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(new Index(int.MaxValue))); + } + + [Fact] + public void EmptySource_Consistency_Collection() + { + int[] source = { }; + + Assert.Throws("index", () => new TestCollection(source).ElementAt(1)); + Assert.Throws("index", () => new TestCollection(source).ElementAt(-1)); + Assert.Throws("index", () => new TestCollection(source).ElementAt(new Index(1))); + Assert.Throws("index", () => new TestCollection(source).ElementAt(^1)); + + Assert.Throws("index", () => new TestCollection(source).ElementAt(0)); + Assert.Throws("index", () => new TestCollection(source).ElementAt(new Index(0))); + Assert.Throws("index", () => new TestCollection(source).ElementAt(^0)); + + Assert.Throws("index", () => new TestCollection(source).ElementAt(int.MinValue)); + Assert.Throws("index", () => new TestCollection(source).ElementAt(^int.MaxValue)); + + Assert.Throws("index", () => new TestCollection(source).ElementAt(int.MaxValue)); + Assert.Throws("index", () => new TestCollection(source).ElementAt(new Index(int.MaxValue))); + } + + [Fact] + public void EmptySource_Consistency_NonGenericCollection() + { + int[] source = { }; + + Assert.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(1)); + Assert.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(-1)); + Assert.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(new Index(1))); + Assert.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(^1)); + + Assert.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(0)); + Assert.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(new Index(0))); + Assert.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(^0)); + + Assert.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(int.MinValue)); + Assert.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(^int.MaxValue)); + + Assert.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(int.MaxValue)); + Assert.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(new Index(int.MaxValue))); } } } diff --git a/src/libraries/System.Linq/tests/EnumerableTests.cs b/src/libraries/System.Linq/tests/EnumerableTests.cs index 1bb71e61df008..16869e2654a05 100644 --- a/src/libraries/System.Linq/tests/EnumerableTests.cs +++ b/src/libraries/System.Linq/tests/EnumerableTests.cs @@ -3,6 +3,7 @@ using System.Collections; using System.Collections.Generic; +using Xunit; namespace System.Linq.Tests { @@ -241,6 +242,28 @@ protected static IEnumerable FlipIsCollection(IEnumerable source) { return source is ICollection ? ForceNotCollection(source) : new List(source); } + protected static T[] Repeat(Func factory, int count) + { + T[] results = new T[count]; + for (int index = 0; index < results.Length; index++) + { + results[index] = factory(index); + } + + return results; + } + + protected static IEnumerable ListPartitionOrEmpty(IList source) // Or Empty + { + var listPartition = source.Skip(0); + return listPartition; + } + + protected static IEnumerable EnumerablePartitionOrEmpty(IEnumerable source) // Or Empty + { + var enumerablePartition = ForceNotCollection(source).Skip(0); + return enumerablePartition; + } protected struct StringWithIntArray { diff --git a/src/libraries/System.Linq/tests/TakeTests.cs b/src/libraries/System.Linq/tests/TakeTests.cs index 239ec1f9ed716..1eea3e9c74f65 100644 --- a/src/libraries/System.Linq/tests/TakeTests.cs +++ b/src/libraries/System.Linq/tests/TakeTests.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; using System.Collections.Generic; using Xunit; @@ -9,12 +8,6 @@ namespace System.Linq.Tests { public class TakeTests : EnumerableTests { - private static IEnumerable GuaranteeNotIList(IEnumerable source) - { - foreach (T element in source) - yield return element; - } - [Fact] public void SameResultsRepeatCallsIntQuery() { @@ -23,6 +16,11 @@ where x > int.MinValue select x; Assert.Equal(q.Take(9), q.Take(9)); + + Assert.Equal(q.Take(0..9), q.Take(0..9)); + Assert.Equal(q.Take(^9..9), q.Take(^9..9)); + Assert.Equal(q.Take(0..^0), q.Take(0..^0)); + Assert.Equal(q.Take(^9..^0), q.Take(^9..^0)); } [Fact] @@ -33,6 +31,11 @@ where x > Int32.MinValue select x).ToList(); Assert.Equal(q.Take(9), q.Take(9)); + + Assert.Equal(q.Take(0..9), q.Take(0..9)); + Assert.Equal(q.Take(^9..9), q.Take(^9..9)); + Assert.Equal(q.Take(0..^0), q.Take(0..^0)); + Assert.Equal(q.Take(^9..^0), q.Take(^9..^0)); } [Fact] @@ -43,6 +46,11 @@ public void SameResultsRepeatCallsStringQuery() select x; Assert.Equal(q.Take(7), q.Take(7)); + + Assert.Equal(q.Take(0..7), q.Take(0..7)); + Assert.Equal(q.Take(^7..7), q.Take(^7..7)); + Assert.Equal(q.Take(0..^0), q.Take(0..^0)); + Assert.Equal(q.Take(^7..^0), q.Take(^7..^0)); } [Fact] @@ -53,13 +61,23 @@ public void SameResultsRepeatCallsStringQueryIList() select x).ToList(); Assert.Equal(q.Take(7), q.Take(7)); + + Assert.Equal(q.Take(0..7), q.Take(0..7)); + Assert.Equal(q.Take(^7..7), q.Take(^7..7)); + Assert.Equal(q.Take(0..^0), q.Take(0..^0)); + Assert.Equal(q.Take(^7..^0), q.Take(^7..^0)); } [Fact] public void SourceEmptyCountPositive() { - int[] source = { }; + var source = new int[] { }; Assert.Empty(source.Take(5)); + + Assert.Empty(source.Take(0..5)); + Assert.Empty(source.Take(^5..5)); + Assert.Empty(source.Take(0..^0)); + Assert.Empty(source.Take(^5..^0)); } [Fact] @@ -67,127 +85,208 @@ public void SourceEmptyCountPositiveNotIList() { var source = NumberRangeGuaranteedNotCollectionType(0, 0); Assert.Empty(source.Take(5)); + + Assert.Empty(source.Take(0..5)); + Assert.Empty(source.Take(^5..5)); + Assert.Empty(source.Take(0..^0)); + Assert.Empty(source.Take(^5..^0)); } [Fact] public void SourceNonEmptyCountNegative() { - int[] source = { 2, 5, 9, 1 }; + var source = new[] { 2, 5, 9, 1 }; Assert.Empty(source.Take(-5)); + + Assert.Empty(source.Take(^9..0)); } [Fact] public void SourceNonEmptyCountNegativeNotIList() { - var source = GuaranteeNotIList(new[] { 2, 5, 9, 1 }); + var source = ForceNotCollection(new[] { 2, 5, 9, 1 }); Assert.Empty(source.Take(-5)); + + Assert.Empty(source.Take(^9..0)); } [Fact] public void SourceNonEmptyCountZero() { - int[] source = { 2, 5, 9, 1 }; + var source = new[] { 2, 5, 9, 1 }; Assert.Empty(source.Take(0)); + + Assert.Empty(source.Take(0..0)); + Assert.Empty(source.Take(^4..0)); + Assert.Empty(source.Take(0..^4)); + Assert.Empty(source.Take(^4..^4)); } [Fact] public void SourceNonEmptyCountZeroNotIList() { - var source = GuaranteeNotIList(new[] { 2, 5, 9, 1 }); + var source = ForceNotCollection(new[] { 2, 5, 9, 1 }); Assert.Empty(source.Take(0)); + + Assert.Empty(source.Take(0..0)); + Assert.Empty(source.Take(^4..0)); + Assert.Empty(source.Take(0..^4)); + Assert.Empty(source.Take(^4..^4)); } [Fact] public void SourceNonEmptyCountOne() { - int[] source = { 2, 5, 9, 1 }; + var source = new[] { 2, 5, 9, 1 }; int[] expected = { 2 }; Assert.Equal(expected, source.Take(1)); + + Assert.Equal(expected, source.Take(0..1)); + Assert.Equal(expected, source.Take(^4..1)); + Assert.Equal(expected, source.Take(0..^3)); + Assert.Equal(expected, source.Take(^4..^3)); } [Fact] public void SourceNonEmptyCountOneNotIList() { - var source = GuaranteeNotIList(new[] { 2, 5, 9, 1 }); + var source = ForceNotCollection(new[] { 2, 5, 9, 1 }); int[] expected = { 2 }; Assert.Equal(expected, source.Take(1)); + + Assert.Equal(expected, source.Take(0..1)); + Assert.Equal(expected, source.Take(^4..1)); + Assert.Equal(expected, source.Take(0..^3)); + Assert.Equal(expected, source.Take(^4..^3)); } [Fact] public void SourceNonEmptyTakeAllExactly() { - int[] source = { 2, 5, 9, 1 }; + var source = new[] { 2, 5, 9, 1 }; Assert.Equal(source, source.Take(source.Length)); + + Assert.Equal(source, source.Take(0..source.Length)); + Assert.Equal(source, source.Take(^source.Length..source.Length)); + Assert.Equal(source, source.Take(0..^0)); + Assert.Equal(source, source.Take(^source.Length..^0)); } [Fact] public void SourceNonEmptyTakeAllExactlyNotIList() { - var source = GuaranteeNotIList(new[] { 2, 5, 9, 1 }); + var source = ForceNotCollection(new[] { 2, 5, 9, 1 }); Assert.Equal(source, source.Take(source.Count())); + + Assert.Equal(source, source.Take(0..source.Count())); + Assert.Equal(source, source.Take(^source.Count()..source.Count())); + Assert.Equal(source, source.Take(0..^0)); + Assert.Equal(source, source.Take(^source.Count()..^0)); } [Fact] public void SourceNonEmptyTakeAllButOne() { - int[] source = { 2, 5, 9, 1 }; + var source = new[] { 2, 5, 9, 1 }; int[] expected = { 2, 5, 9 }; Assert.Equal(expected, source.Take(3)); + + Assert.Equal(expected, source.Take(0..3)); + Assert.Equal(expected, source.Take(^4..3)); + Assert.Equal(expected, source.Take(0..^1)); + Assert.Equal(expected, source.Take(^4..^1)); } [Fact] public void RunOnce() { - int[] source = { 2, 5, 9, 1 }; + var source = new[] { 2, 5, 9, 1 }; int[] expected = { 2, 5, 9 }; Assert.Equal(expected, source.RunOnce().Take(3)); + + Assert.Equal(expected, source.RunOnce().Take(0..3)); + Assert.Equal(expected, source.RunOnce().Take(^4..3)); + Assert.Equal(expected, source.RunOnce().Take(0..^1)); + Assert.Equal(expected, source.RunOnce().Take(^4..^1)); } [Fact] public void SourceNonEmptyTakeAllButOneNotIList() { - var source = GuaranteeNotIList(new[] { 2, 5, 9, 1 }); + var source = ForceNotCollection(new[] { 2, 5, 9, 1 }); int[] expected = { 2, 5, 9 }; - Assert.Equal(expected, source.Take(3)); + Assert.Equal(expected, source.RunOnce().Take(3)); + + Assert.Equal(expected, source.RunOnce().Take(0..3)); + Assert.Equal(expected, source.RunOnce().Take(^4..3)); + Assert.Equal(expected, source.RunOnce().Take(0..^1)); + Assert.Equal(expected, source.RunOnce().Take(^4..^1)); } [Fact] public void SourceNonEmptyTakeExcessive() { - int?[] source = { 2, 5, null, 9, 1 }; + var source = new int?[] { 2, 5, null, 9, 1 }; Assert.Equal(source, source.Take(source.Length + 1)); + + Assert.Equal(source, source.Take(0..(source.Length + 1))); + Assert.Equal(source, source.Take(^(source.Length + 1)..(source.Length + 1))); } [Fact] public void SourceNonEmptyTakeExcessiveNotIList() { - var source = GuaranteeNotIList(new int?[] { 2, 5, null, 9, 1 }); + var source = ForceNotCollection(new int?[] { 2, 5, null, 9, 1 }); Assert.Equal(source, source.Take(source.Count() + 1)); + + Assert.Equal(source, source.Take(0..(source.Count() + 1))); + Assert.Equal(source, source.Take(^(source.Count() + 1)..(source.Count() + 1))); } [Fact] public void ThrowsOnNullSource() { int[] source = null; - AssertExtensions.Throws("source", () => source.Take(5)); + Assert.Throws("source", () => source.Take(5)); + + Assert.Throws("source", () => source.Take(0..5)); + Assert.Throws("source", () => source.Take(^5..5)); + Assert.Throws("source", () => source.Take(0..^0)); + Assert.Throws("source", () => source.Take(^5..^0)); } [Fact] - public void ForcedToEnumeratorDoesntEnumerate() + public void ForcedToEnumeratorDoesNotEnumerate() { - var iterator = NumberRangeGuaranteedNotCollectionType(0, 3).Take(2); + var iterator1 = NumberRangeGuaranteedNotCollectionType(0, 3).Take(2); // Don't insist on this behaviour, but check it's correct if it happens - var en = iterator as IEnumerator; - Assert.False(en != null && en.MoveNext()); + var en1 = iterator1 as IEnumerator; + Assert.False(en1 != null && en1.MoveNext()); + + var iterator2 = NumberRangeGuaranteedNotCollectionType(0, 3).Take(0..2); + var en2 = iterator2 as IEnumerator; + Assert.False(en2 != null && en2.MoveNext()); + + var iterator3 = NumberRangeGuaranteedNotCollectionType(0, 3).Take(^3..2); + var en3 = iterator3 as IEnumerator; + Assert.False(en3 != null && en3.MoveNext()); + + var iterator4 = NumberRangeGuaranteedNotCollectionType(0, 3).Take(0..^1); + var en4 = iterator4 as IEnumerator; + Assert.False(en4 != null && en4.MoveNext()); + + var iterator5 = NumberRangeGuaranteedNotCollectionType(0, 3).Take(^3..^1); + var en5 = iterator5 as IEnumerator; + Assert.False(en5 != null && en5.MoveNext()); } [Fact] @@ -196,15 +295,47 @@ public void Count() Assert.Equal(2, NumberRangeGuaranteedNotCollectionType(0, 3).Take(2).Count()); Assert.Equal(2, new[] { 1, 2, 3 }.Take(2).Count()); Assert.Equal(0, NumberRangeGuaranteedNotCollectionType(0, 3).Take(0).Count()); + + Assert.Equal(2, NumberRangeGuaranteedNotCollectionType(0, 3).Take(0..2).Count()); + Assert.Equal(2, new[] { 1, 2, 3 }.Take(0..2).Count()); + Assert.Equal(0, NumberRangeGuaranteedNotCollectionType(0, 3).Take(0..0).Count()); + + Assert.Equal(2, NumberRangeGuaranteedNotCollectionType(0, 3).Take(^3..2).Count()); + Assert.Equal(2, new[] { 1, 2, 3 }.Take(^3..2).Count()); + Assert.Equal(0, NumberRangeGuaranteedNotCollectionType(0, 3).Take(^3..0).Count()); + + Assert.Equal(2, NumberRangeGuaranteedNotCollectionType(0, 3).Take(0..^1).Count()); + Assert.Equal(2, new[] { 1, 2, 3 }.Take(0..^1).Count()); + Assert.Equal(0, NumberRangeGuaranteedNotCollectionType(0, 3).Take(0..^3).Count()); + + Assert.Equal(2, NumberRangeGuaranteedNotCollectionType(0, 3).Take(^3..^1).Count()); + Assert.Equal(2, new[] { 1, 2, 3 }.Take(^3..^1).Count()); + Assert.Equal(0, NumberRangeGuaranteedNotCollectionType(0, 3).Take(^3..^3).Count()); } [Fact] public void ForcedToEnumeratorDoesntEnumerateIList() { - var iterator = NumberRangeGuaranteedNotCollectionType(0, 3).ToList().Take(2); + var iterator1 = NumberRangeGuaranteedNotCollectionType(0, 3).ToList().Take(2); // Don't insist on this behaviour, but check it's correct if it happens - var en = iterator as IEnumerator; - Assert.False(en != null && en.MoveNext()); + var en1 = iterator1 as IEnumerator; + Assert.False(en1 != null && en1.MoveNext()); + + var iterator2 = NumberRangeGuaranteedNotCollectionType(0, 3).ToList().Take(0..2); + var en2 = iterator2 as IEnumerator; + Assert.False(en2 != null && en2.MoveNext()); + + var iterator3 = NumberRangeGuaranteedNotCollectionType(0, 3).ToList().Take(^3..2); + var en3 = iterator3 as IEnumerator; + Assert.False(en3 != null && en3.MoveNext()); + + var iterator4 = NumberRangeGuaranteedNotCollectionType(0, 3).ToList().Take(0..^1); + var en4 = iterator4 as IEnumerator; + Assert.False(en4 != null && en4.MoveNext()); + + var iterator5 = NumberRangeGuaranteedNotCollectionType(0, 3).ToList().Take(^3..^1); + var en5 = iterator5 as IEnumerator; + Assert.False(en5 != null && en5.MoveNext()); } [Fact] @@ -213,6 +344,11 @@ public void FollowWithTake() var source = new[] { 5, 6, 7, 8 }; var expected = new[] { 5, 6 }; Assert.Equal(expected, source.Take(5).Take(3).Take(2).Take(40)); + + Assert.Equal(expected, source.Take(0..5).Take(0..3).Take(0..2).Take(0..40)); + Assert.Equal(expected, source.Take(^4..5).Take(^4..3).Take(^3..2).Take(^2..40)); + Assert.Equal(expected, source.Take(0..^0).Take(0..^1).Take(0..^1).Take(0..^0)); + Assert.Equal(expected, source.Take(^4..^0).Take(^4..^1).Take(^3..^1).Take(^2..^0)); } [Fact] @@ -221,6 +357,11 @@ public void FollowWithTakeNotIList() var source = NumberRangeGuaranteedNotCollectionType(5, 4); var expected = new[] { 5, 6 }; Assert.Equal(expected, source.Take(5).Take(3).Take(2)); + + Assert.Equal(expected, source.Take(0..5).Take(0..3).Take(0..2)); + Assert.Equal(expected, source.Take(^4..5).Take(^4..3).Take(^3..2)); + Assert.Equal(expected, source.Take(0..^0).Take(0..^1).Take(0..^1)); + Assert.Equal(expected, source.Take(^4..^0).Take(^4..^1).Take(^3..^1)); } [Fact] @@ -229,6 +370,11 @@ public void FollowWithSkip() var source = new[] { 1, 2, 3, 4, 5, 6 }; var expected = new[] { 3, 4, 5 }; Assert.Equal(expected, source.Take(5).Skip(2).Skip(-4)); + + Assert.Equal(expected, source.Take(0..5).Skip(2).Skip(-4)); + Assert.Equal(expected, source.Take(^6..5).Skip(2).Skip(-4)); + Assert.Equal(expected, source.Take(0..^1).Skip(2).Skip(-4)); + Assert.Equal(expected, source.Take(^6..^1).Skip(2).Skip(-4)); } [Fact] @@ -237,50 +383,151 @@ public void FollowWithSkipNotIList() var source = NumberRangeGuaranteedNotCollectionType(1, 6); var expected = new[] { 3, 4, 5 }; Assert.Equal(expected, source.Take(5).Skip(2).Skip(-4)); + + Assert.Equal(expected, source.Take(0..5).Skip(2).Skip(-4)); + Assert.Equal(expected, source.Take(^6..5).Skip(2).Skip(-4)); + Assert.Equal(expected, source.Take(0..^1).Skip(2).Skip(-4)); + Assert.Equal(expected, source.Take(^6..^1).Skip(2).Skip(-4)); } [Fact] public void ElementAt() { var source = new[] { 1, 2, 3, 4, 5, 6 }; - var taken = source.Take(3); - Assert.Equal(1, taken.ElementAt(0)); - Assert.Equal(3, taken.ElementAt(2)); - AssertExtensions.Throws("index", () => taken.ElementAt(-1)); - AssertExtensions.Throws("index", () => taken.ElementAt(3)); + var taken0 = source.Take(3); + Assert.Equal(1, taken0.ElementAt(0)); + Assert.Equal(3, taken0.ElementAt(2)); + Assert.Throws("index", () => taken0.ElementAt(-1)); + Assert.Throws("index", () => taken0.ElementAt(3)); + + var taken1 = source.Take(0..3); + Assert.Equal(1, taken1.ElementAt(0)); + Assert.Equal(3, taken1.ElementAt(2)); + Assert.Throws("index", () => taken1.ElementAt(-1)); + Assert.Throws("index", () => taken1.ElementAt(3)); + + var taken2 = source.Take(^6..3); + Assert.Equal(1, taken2.ElementAt(0)); + Assert.Equal(3, taken2.ElementAt(2)); + Assert.Throws("index", () => taken2.ElementAt(-1)); + Assert.Throws("index", () => taken2.ElementAt(3)); + + var taken3 = source.Take(0..^3); + Assert.Equal(1, taken3.ElementAt(0)); + Assert.Equal(3, taken3.ElementAt(2)); + Assert.Throws("index", () => taken3.ElementAt(-1)); + Assert.Throws("index", () => taken3.ElementAt(3)); + + var taken4 = source.Take(^6..^3); + Assert.Equal(1, taken4.ElementAt(0)); + Assert.Equal(3, taken4.ElementAt(2)); + Assert.Throws("index", () => taken4.ElementAt(-1)); + Assert.Throws("index", () => taken4.ElementAt(3)); } [Fact] public void ElementAtNotIList() { - var source = GuaranteeNotIList(new[] { 1, 2, 3, 4, 5, 6 }); - var taken = source.Take(3); - Assert.Equal(1, taken.ElementAt(0)); - Assert.Equal(3, taken.ElementAt(2)); - AssertExtensions.Throws("index", () => taken.ElementAt(-1)); - AssertExtensions.Throws("index", () => taken.ElementAt(3)); + var source = ForceNotCollection(new[] { 1, 2, 3, 4, 5, 6 }); + var taken0 = source.Take(3); + Assert.Equal(1, taken0.ElementAt(0)); + Assert.Equal(3, taken0.ElementAt(2)); + Assert.Throws("index", () => taken0.ElementAt(-1)); + Assert.Throws("index", () => taken0.ElementAt(3)); + + var taken1 = source.Take(0..3); + Assert.Equal(1, taken1.ElementAt(0)); + Assert.Equal(3, taken1.ElementAt(2)); + Assert.Throws("index", () => taken1.ElementAt(-1)); + Assert.Throws("index", () => taken1.ElementAt(3)); + + var taken2 = source.Take(^6..3); + Assert.Equal(1, taken2.ElementAt(0)); + Assert.Equal(3, taken2.ElementAt(2)); + Assert.Throws("index", () => taken2.ElementAt(-1)); + Assert.Throws("index", () => taken2.ElementAt(3)); + + var taken3 = source.Take(0..^3); + Assert.Equal(1, taken3.ElementAt(0)); + Assert.Equal(3, taken3.ElementAt(2)); + Assert.Throws("index", () => taken3.ElementAt(-1)); + Assert.Throws("index", () => taken3.ElementAt(3)); + + var taken4 = source.Take(^6..^3); + Assert.Equal(1, taken4.ElementAt(0)); + Assert.Equal(3, taken4.ElementAt(2)); + Assert.Throws("index", () => taken4.ElementAt(-1)); + Assert.Throws("index", () => taken4.ElementAt(3)); } [Fact] public void ElementAtOrDefault() { var source = new[] { 1, 2, 3, 4, 5, 6 }; - var taken = source.Take(3); - Assert.Equal(1, taken.ElementAtOrDefault(0)); - Assert.Equal(3, taken.ElementAtOrDefault(2)); - Assert.Equal(0, taken.ElementAtOrDefault(-1)); - Assert.Equal(0, taken.ElementAtOrDefault(3)); + var taken0 = source.Take(3); + Assert.Equal(1, taken0.ElementAtOrDefault(0)); + Assert.Equal(3, taken0.ElementAtOrDefault(2)); + Assert.Equal(0, taken0.ElementAtOrDefault(-1)); + Assert.Equal(0, taken0.ElementAtOrDefault(3)); + + var taken1 = source.Take(0..3); + Assert.Equal(1, taken1.ElementAtOrDefault(0)); + Assert.Equal(3, taken1.ElementAtOrDefault(2)); + Assert.Equal(0, taken1.ElementAtOrDefault(-1)); + Assert.Equal(0, taken1.ElementAtOrDefault(3)); + + var taken2 = source.Take(^6..3); + Assert.Equal(1, taken2.ElementAtOrDefault(0)); + Assert.Equal(3, taken2.ElementAtOrDefault(2)); + Assert.Equal(0, taken2.ElementAtOrDefault(-1)); + Assert.Equal(0, taken2.ElementAtOrDefault(3)); + + var taken3 = source.Take(0..^3); + Assert.Equal(1, taken3.ElementAtOrDefault(0)); + Assert.Equal(3, taken3.ElementAtOrDefault(2)); + Assert.Equal(0, taken3.ElementAtOrDefault(-1)); + Assert.Equal(0, taken3.ElementAtOrDefault(3)); + + var taken4 = source.Take(^6..^3); + Assert.Equal(1, taken4.ElementAtOrDefault(0)); + Assert.Equal(3, taken4.ElementAtOrDefault(2)); + Assert.Equal(0, taken4.ElementAtOrDefault(-1)); + Assert.Equal(0, taken4.ElementAtOrDefault(3)); } [Fact] public void ElementAtOrDefaultNotIList() { - var source = GuaranteeNotIList(new[] { 1, 2, 3, 4, 5, 6 }); - var taken = source.Take(3); - Assert.Equal(1, taken.ElementAtOrDefault(0)); - Assert.Equal(3, taken.ElementAtOrDefault(2)); - Assert.Equal(0, taken.ElementAtOrDefault(-1)); - Assert.Equal(0, taken.ElementAtOrDefault(3)); + var source = ForceNotCollection(new[] { 1, 2, 3, 4, 5, 6 }); + var taken0 = source.Take(3); + Assert.Equal(1, taken0.ElementAtOrDefault(0)); + Assert.Equal(3, taken0.ElementAtOrDefault(2)); + Assert.Equal(0, taken0.ElementAtOrDefault(-1)); + Assert.Equal(0, taken0.ElementAtOrDefault(3)); + + var taken1 = source.Take(0..3); + Assert.Equal(1, taken1.ElementAtOrDefault(0)); + Assert.Equal(3, taken1.ElementAtOrDefault(2)); + Assert.Equal(0, taken1.ElementAtOrDefault(-1)); + Assert.Equal(0, taken1.ElementAtOrDefault(3)); + + var taken2 = source.Take(^6..3); + Assert.Equal(1, taken2.ElementAtOrDefault(0)); + Assert.Equal(3, taken2.ElementAtOrDefault(2)); + Assert.Equal(0, taken2.ElementAtOrDefault(-1)); + Assert.Equal(0, taken2.ElementAtOrDefault(3)); + + var taken3 = source.Take(0..^3); + Assert.Equal(1, taken3.ElementAtOrDefault(0)); + Assert.Equal(3, taken3.ElementAtOrDefault(2)); + Assert.Equal(0, taken3.ElementAtOrDefault(-1)); + Assert.Equal(0, taken3.ElementAtOrDefault(3)); + + var taken4 = source.Take(^6..^3); + Assert.Equal(1, taken4.ElementAtOrDefault(0)); + Assert.Equal(3, taken4.ElementAtOrDefault(2)); + Assert.Equal(0, taken4.ElementAtOrDefault(-1)); + Assert.Equal(0, taken4.ElementAtOrDefault(3)); } [Fact] @@ -292,17 +539,65 @@ public void First() Assert.Equal(1, source.Take(40).First()); Assert.Throws(() => source.Take(0).First()); Assert.Throws(() => source.Skip(5).Take(10).First()); + + Assert.Equal(1, source.Take(0..1).First()); + Assert.Equal(1, source.Take(0..4).First()); + Assert.Equal(1, source.Take(0..40).First()); + Assert.Throws(() => source.Take(0..0).First()); + Assert.Throws(() => source.Skip(5).Take(0..10).First()); + + Assert.Equal(1, source.Take(^5..1).First()); + Assert.Equal(1, source.Take(^5..4).First()); + Assert.Equal(1, source.Take(^5..40).First()); + Assert.Throws(() => source.Take(^5..0).First()); + Assert.Throws(() => source.Skip(5).Take(^5..10).First()); + + Assert.Equal(1, source.Take(0..^4).First()); + Assert.Equal(1, source.Take(0..^1).First()); + Assert.Equal(1, source.Take(0..^0).First()); + Assert.Throws(() => source.Take(0..^5).First()); + Assert.Throws(() => source.Skip(5).Take(0..^5).First()); + + Assert.Equal(1, source.Take(^5..^4).First()); + Assert.Equal(1, source.Take(^5..^1).First()); + Assert.Equal(1, source.Take(^5..^0).First()); + Assert.Throws(() => source.Take(^5..^5).First()); + Assert.Throws(() => source.Skip(5).Take(^10..^0).First()); } [Fact] public void FirstNotIList() { - var source = GuaranteeNotIList(new[] { 1, 2, 3, 4, 5 }); + var source = ForceNotCollection(new[] { 1, 2, 3, 4, 5 }); Assert.Equal(1, source.Take(1).First()); Assert.Equal(1, source.Take(4).First()); Assert.Equal(1, source.Take(40).First()); Assert.Throws(() => source.Take(0).First()); Assert.Throws(() => source.Skip(5).Take(10).First()); + + Assert.Equal(1, source.Take(0..1).First()); + Assert.Equal(1, source.Take(0..4).First()); + Assert.Equal(1, source.Take(0..40).First()); + Assert.Throws(() => source.Take(0..0).First()); + Assert.Throws(() => source.Skip(5).Take(0..10).First()); + + Assert.Equal(1, source.Take(^5..1).First()); + Assert.Equal(1, source.Take(^5..4).First()); + Assert.Equal(1, source.Take(^5..40).First()); + Assert.Throws(() => source.Take(^5..0).First()); + Assert.Throws(() => source.Skip(5).Take(^5..10).First()); + + Assert.Equal(1, source.Take(0..^4).First()); + Assert.Equal(1, source.Take(0..^1).First()); + Assert.Equal(1, source.Take(0..^0).First()); + Assert.Throws(() => source.Take(0..^5).First()); + Assert.Throws(() => source.Skip(5).Take(0..^5).First()); + + Assert.Equal(1, source.Take(^5..^4).First()); + Assert.Equal(1, source.Take(^5..^1).First()); + Assert.Equal(1, source.Take(^5..^0).First()); + Assert.Throws(() => source.Take(^5..^5).First()); + Assert.Throws(() => source.Skip(5).Take(^10..^0).First()); } [Fact] @@ -314,17 +609,65 @@ public void FirstOrDefault() Assert.Equal(1, source.Take(40).FirstOrDefault()); Assert.Equal(0, source.Take(0).FirstOrDefault()); Assert.Equal(0, source.Skip(5).Take(10).FirstOrDefault()); + + Assert.Equal(1, source.Take(0..1).FirstOrDefault()); + Assert.Equal(1, source.Take(0..4).FirstOrDefault()); + Assert.Equal(1, source.Take(0..40).FirstOrDefault()); + Assert.Equal(0, source.Take(0..0).FirstOrDefault()); + Assert.Equal(0, source.Skip(5).Take(0..10).FirstOrDefault()); + + Assert.Equal(1, source.Take(^5..1).FirstOrDefault()); + Assert.Equal(1, source.Take(^5..4).FirstOrDefault()); + Assert.Equal(1, source.Take(^5..40).FirstOrDefault()); + Assert.Equal(0, source.Take(^5..0).FirstOrDefault()); + Assert.Equal(0, source.Skip(5).Take(^10..10).FirstOrDefault()); + + Assert.Equal(1, source.Take(0..^4).FirstOrDefault()); + Assert.Equal(1, source.Take(0..^1).FirstOrDefault()); + Assert.Equal(1, source.Take(0..^0).FirstOrDefault()); + Assert.Equal(0, source.Take(0..^5).FirstOrDefault()); + Assert.Equal(0, source.Skip(5).Take(0..^10).FirstOrDefault()); + + Assert.Equal(1, source.Take(^5..^4).FirstOrDefault()); + Assert.Equal(1, source.Take(^5..^1).FirstOrDefault()); + Assert.Equal(1, source.Take(^5..^0).FirstOrDefault()); + Assert.Equal(0, source.Take(^5..^5).FirstOrDefault()); + Assert.Equal(0, source.Skip(5).Take(^10..^0).FirstOrDefault()); } [Fact] public void FirstOrDefaultNotIList() { - var source = GuaranteeNotIList(new[] { 1, 2, 3, 4, 5 }); + var source = ForceNotCollection(new[] { 1, 2, 3, 4, 5 }); Assert.Equal(1, source.Take(1).FirstOrDefault()); Assert.Equal(1, source.Take(4).FirstOrDefault()); Assert.Equal(1, source.Take(40).FirstOrDefault()); Assert.Equal(0, source.Take(0).FirstOrDefault()); Assert.Equal(0, source.Skip(5).Take(10).FirstOrDefault()); + + Assert.Equal(1, source.Take(0..1).FirstOrDefault()); + Assert.Equal(1, source.Take(0..4).FirstOrDefault()); + Assert.Equal(1, source.Take(0..40).FirstOrDefault()); + Assert.Equal(0, source.Take(0..0).FirstOrDefault()); + Assert.Equal(0, source.Skip(5).Take(0..10).FirstOrDefault()); + + Assert.Equal(1, source.Take(^5..1).FirstOrDefault()); + Assert.Equal(1, source.Take(^5..4).FirstOrDefault()); + Assert.Equal(1, source.Take(^5..40).FirstOrDefault()); + Assert.Equal(0, source.Take(^5..0).FirstOrDefault()); + Assert.Equal(0, source.Skip(5).Take(^10..10).FirstOrDefault()); + + Assert.Equal(1, source.Take(0..^4).FirstOrDefault()); + Assert.Equal(1, source.Take(0..^1).FirstOrDefault()); + Assert.Equal(1, source.Take(0..^0).FirstOrDefault()); + Assert.Equal(0, source.Take(0..^5).FirstOrDefault()); + Assert.Equal(0, source.Skip(5).Take(0..^10).FirstOrDefault()); + + Assert.Equal(1, source.Take(^5..^4).FirstOrDefault()); + Assert.Equal(1, source.Take(^5..^1).FirstOrDefault()); + Assert.Equal(1, source.Take(^5..^0).FirstOrDefault()); + Assert.Equal(0, source.Take(^5..^5).FirstOrDefault()); + Assert.Equal(0, source.Skip(5).Take(^10..^0).FirstOrDefault()); } [Fact] @@ -336,17 +679,65 @@ public void Last() Assert.Equal(5, source.Take(40).Last()); Assert.Throws(() => source.Take(0).Last()); Assert.Throws(() => Array.Empty().Take(40).Last()); + + Assert.Equal(1, source.Take(0..1).Last()); + Assert.Equal(5, source.Take(0..5).Last()); + Assert.Equal(5, source.Take(0..40).Last()); + Assert.Throws(() => source.Take(0..0).Last()); + Assert.Throws(() => Array.Empty().Take(0..40).Last()); + + Assert.Equal(1, source.Take(^5..1).Last()); + Assert.Equal(5, source.Take(^5..5).Last()); + Assert.Equal(5, source.Take(^5..40).Last()); + Assert.Throws(() => source.Take(^5..0).Last()); + Assert.Throws(() => Array.Empty().Take(^5..40).Last()); + + Assert.Equal(1, source.Take(0..^4).Last()); + Assert.Equal(5, source.Take(0..^0).Last()); + Assert.Equal(5, source.Take(3..^0).Last()); + Assert.Throws(() => source.Take(0..^5).Last()); + Assert.Throws(() => Array.Empty().Take(0..^0).Last()); + + Assert.Equal(1, source.Take(^5..^4).Last()); + Assert.Equal(5, source.Take(^5..^0).Last()); + Assert.Equal(5, source.Take(^5..^0).Last()); + Assert.Throws(() => source.Take(^5..^5).Last()); + Assert.Throws(() => Array.Empty().Take(^40..^0).Last()); } [Fact] public void LastNotIList() { - var source = GuaranteeNotIList(new[] { 1, 2, 3, 4, 5 }); + var source = ForceNotCollection(new[] { 1, 2, 3, 4, 5 }); Assert.Equal(1, source.Take(1).Last()); Assert.Equal(5, source.Take(5).Last()); Assert.Equal(5, source.Take(40).Last()); Assert.Throws(() => source.Take(0).Last()); - Assert.Throws(() => GuaranteeNotIList(Array.Empty()).Take(40).Last()); + Assert.Throws(() => ForceNotCollection(Array.Empty()).Take(40).Last()); + + Assert.Equal(1, source.Take(0..1).Last()); + Assert.Equal(5, source.Take(0..5).Last()); + Assert.Equal(5, source.Take(0..40).Last()); + Assert.Throws(() => source.Take(0..0).Last()); + Assert.Throws(() => ForceNotCollection(Array.Empty()).Take(0..40).Last()); + + Assert.Equal(1, source.Take(^5..1).Last()); + Assert.Equal(5, source.Take(^5..5).Last()); + Assert.Equal(5, source.Take(^5..40).Last()); + Assert.Throws(() => source.Take(^5..0).Last()); + Assert.Throws(() => ForceNotCollection(Array.Empty()).Take(^5..40).Last()); + + Assert.Equal(1, source.Take(0..^4).Last()); + Assert.Equal(5, source.Take(0..^0).Last()); + Assert.Equal(5, source.Take(3..^0).Last()); + Assert.Throws(() => source.Take(0..^5).Last()); + Assert.Throws(() => ForceNotCollection(Array.Empty()).Take(0..^0).Last()); + + Assert.Equal(1, source.Take(^5..^4).Last()); + Assert.Equal(5, source.Take(^5..^0).Last()); + Assert.Equal(5, source.Take(^5..^0).Last()); + Assert.Throws(() => source.Take(^5..^5).Last()); + Assert.Throws(() => ForceNotCollection(Array.Empty()).Take(^40..^0).Last()); } [Fact] @@ -358,17 +749,65 @@ public void LastOrDefault() Assert.Equal(5, source.Take(40).LastOrDefault()); Assert.Equal(0, source.Take(0).LastOrDefault()); Assert.Equal(0, Array.Empty().Take(40).LastOrDefault()); + + Assert.Equal(1, source.Take(0..1).LastOrDefault()); + Assert.Equal(5, source.Take(0..5).LastOrDefault()); + Assert.Equal(5, source.Take(0..40).LastOrDefault()); + Assert.Equal(0, source.Take(0..0).LastOrDefault()); + Assert.Equal(0, Array.Empty().Take(0..40).LastOrDefault()); + + Assert.Equal(1, source.Take(^5..1).LastOrDefault()); + Assert.Equal(5, source.Take(^5..5).LastOrDefault()); + Assert.Equal(5, source.Take(^5..40).LastOrDefault()); + Assert.Equal(0, source.Take(^5..0).LastOrDefault()); + Assert.Equal(0, Array.Empty().Take(^5..40).LastOrDefault()); + + Assert.Equal(1, source.Take(0..^4).LastOrDefault()); + Assert.Equal(5, source.Take(0..^0).LastOrDefault()); + Assert.Equal(5, source.Take(3..^0).LastOrDefault()); + Assert.Equal(0, source.Take(0..^5).LastOrDefault()); + Assert.Equal(0, Array.Empty().Take(0..^0).LastOrDefault()); + + Assert.Equal(1, source.Take(^5..^4).LastOrDefault()); + Assert.Equal(5, source.Take(^5..^0).LastOrDefault()); + Assert.Equal(5, source.Take(^40..^0).LastOrDefault()); + Assert.Equal(0, source.Take(^5..^5).LastOrDefault()); + Assert.Equal(0, Array.Empty().Take(^40..^0).LastOrDefault()); } [Fact] public void LastOrDefaultNotIList() { - var source = GuaranteeNotIList(new[] { 1, 2, 3, 4, 5 }); + var source = ForceNotCollection(new[] { 1, 2, 3, 4, 5 }); Assert.Equal(1, source.Take(1).LastOrDefault()); Assert.Equal(5, source.Take(5).LastOrDefault()); Assert.Equal(5, source.Take(40).LastOrDefault()); Assert.Equal(0, source.Take(0).LastOrDefault()); - Assert.Equal(0, GuaranteeNotIList(Array.Empty()).Take(40).LastOrDefault()); + Assert.Equal(0, ForceNotCollection(Array.Empty()).Take(40).LastOrDefault()); + + Assert.Equal(1, source.Take(0..1).LastOrDefault()); + Assert.Equal(5, source.Take(0..5).LastOrDefault()); + Assert.Equal(5, source.Take(0..40).LastOrDefault()); + Assert.Equal(0, source.Take(0..0).LastOrDefault()); + Assert.Equal(0, ForceNotCollection(Array.Empty()).Take(0..40).LastOrDefault()); + + Assert.Equal(1, source.Take(^5..1).LastOrDefault()); + Assert.Equal(5, source.Take(^5..5).LastOrDefault()); + Assert.Equal(5, source.Take(^5..40).LastOrDefault()); + Assert.Equal(0, source.Take(^5..0).LastOrDefault()); + Assert.Equal(0, ForceNotCollection(Array.Empty()).Take(^5..40).LastOrDefault()); + + Assert.Equal(1, source.Take(0..^4).LastOrDefault()); + Assert.Equal(5, source.Take(0..^0).LastOrDefault()); + Assert.Equal(5, source.Take(3..^0).LastOrDefault()); + Assert.Equal(0, source.Take(0..^5).LastOrDefault()); + Assert.Equal(0, ForceNotCollection(Array.Empty()).Take(0..^0).LastOrDefault()); + + Assert.Equal(1, source.Take(^5..^4).LastOrDefault()); + Assert.Equal(5, source.Take(^5..^0).LastOrDefault()); + Assert.Equal(5, source.Take(^40..^0).LastOrDefault()); + Assert.Equal(0, source.Take(^5..^5).LastOrDefault()); + Assert.Equal(0, ForceNotCollection(Array.Empty()).Take(^40..^0).LastOrDefault()); } [Fact] @@ -382,12 +821,41 @@ public void ToArray() Assert.Equal(1, source.Take(1).ToArray().Single()); Assert.Empty(source.Take(0).ToArray()); Assert.Empty(source.Take(-10).ToArray()); + + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(0..5).ToArray()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(0..6).ToArray()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(0..40).ToArray()); + Assert.Equal(new[] { 1, 2, 3, 4 }, source.Take(0..4).ToArray()); + Assert.Equal(1, source.Take(0..1).ToArray().Single()); + Assert.Empty(source.Take(0..0).ToArray()); + + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(^5..5).ToArray()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(^5..6).ToArray()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(^5..40).ToArray()); + Assert.Equal(new[] { 1, 2, 3, 4 }, source.Take(^5..4).ToArray()); + Assert.Equal(1, source.Take(^5..1).ToArray().Single()); + Assert.Empty(source.Take(^5..0).ToArray()); + Assert.Empty(source.Take(^15..0).ToArray()); + + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(0..^0).ToArray()); + Assert.Equal(new[] { 1, 2, 3, 4 }, source.Take(0..^1).ToArray()); + Assert.Equal(1, source.Take(0..^4).ToArray().Single()); + Assert.Empty(source.Take(0..^5).ToArray()); + Assert.Empty(source.Take(0..^15).ToArray()); + + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(^5..^0).ToArray()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(^6..^0).ToArray()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(^45..^0).ToArray()); + Assert.Equal(new[] { 1, 2, 3, 4 }, source.Take(^5..^1).ToArray()); + Assert.Equal(1, source.Take(^5..^4).ToArray().Single()); + Assert.Empty(source.Take(^5..^5).ToArray()); + Assert.Empty(source.Take(^15..^5).ToArray()); } [Fact] public void ToArrayNotList() { - var source = GuaranteeNotIList(new[] { 1, 2, 3, 4, 5 }); + var source = ForceNotCollection(new[] { 1, 2, 3, 4, 5 }); Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(5).ToArray()); Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(6).ToArray()); Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(40).ToArray()); @@ -395,6 +863,35 @@ public void ToArrayNotList() Assert.Equal(1, source.Take(1).ToArray().Single()); Assert.Empty(source.Take(0).ToArray()); Assert.Empty(source.Take(-10).ToArray()); + + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(0..5).ToArray()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(0..6).ToArray()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(0..40).ToArray()); + Assert.Equal(new[] { 1, 2, 3, 4 }, source.Take(0..4).ToArray()); + Assert.Equal(1, source.Take(0..1).ToArray().Single()); + Assert.Empty(source.Take(0..0).ToArray()); + + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(^5..5).ToArray()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(^5..6).ToArray()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(^5..40).ToArray()); + Assert.Equal(new[] { 1, 2, 3, 4 }, source.Take(^5..4).ToArray()); + Assert.Equal(1, source.Take(^5..1).ToArray().Single()); + Assert.Empty(source.Take(^5..0).ToArray()); + Assert.Empty(source.Take(^15..0).ToArray()); + + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(0..^0).ToArray()); + Assert.Equal(new[] { 1, 2, 3, 4 }, source.Take(0..^1).ToArray()); + Assert.Equal(1, source.Take(0..^4).ToArray().Single()); + Assert.Empty(source.Take(0..^5).ToArray()); + Assert.Empty(source.Take(0..^15).ToArray()); + + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(^5..^0).ToArray()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(^6..^0).ToArray()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(^45..^0).ToArray()); + Assert.Equal(new[] { 1, 2, 3, 4 }, source.Take(^5..^1).ToArray()); + Assert.Equal(1, source.Take(^5..^4).ToArray().Single()); + Assert.Empty(source.Take(^5..^5).ToArray()); + Assert.Empty(source.Take(^15..^5).ToArray()); } [Fact] @@ -408,12 +905,41 @@ public void ToList() Assert.Equal(1, source.Take(1).ToList().Single()); Assert.Empty(source.Take(0).ToList()); Assert.Empty(source.Take(-10).ToList()); + + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(0..5).ToList()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(0..6).ToList()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(0..40).ToList()); + Assert.Equal(new[] { 1, 2, 3, 4 }, source.Take(0..4).ToList()); + Assert.Equal(1, source.Take(0..1).ToList().Single()); + Assert.Empty(source.Take(0..0).ToList()); + + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(^5..5).ToList()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(^5..6).ToList()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(^5..40).ToList()); + Assert.Equal(new[] { 1, 2, 3, 4 }, source.Take(^5..4).ToList()); + Assert.Equal(1, source.Take(^5..1).ToList().Single()); + Assert.Empty(source.Take(^5..0).ToList()); + Assert.Empty(source.Take(^15..0).ToList()); + + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(0..^0).ToList()); + Assert.Equal(new[] { 1, 2, 3, 4 }, source.Take(0..^1).ToList()); + Assert.Equal(1, source.Take(0..^4).ToList().Single()); + Assert.Empty(source.Take(0..^5).ToList()); + Assert.Empty(source.Take(0..^15).ToList()); + + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(^5..^0).ToList()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(^6..^0).ToList()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(^45..^0).ToList()); + Assert.Equal(new[] { 1, 2, 3, 4 }, source.Take(^5..^1).ToList()); + Assert.Equal(1, source.Take(^5..^4).ToList().Single()); + Assert.Empty(source.Take(^5..^5).ToList()); + Assert.Empty(source.Take(^15..^5).ToList()); } [Fact] public void ToListNotList() { - var source = GuaranteeNotIList(new[] { 1, 2, 3, 4, 5 }); + var source = ForceNotCollection(new[] { 1, 2, 3, 4, 5 }); Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(5).ToList()); Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(6).ToList()); Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(40).ToList()); @@ -421,6 +947,35 @@ public void ToListNotList() Assert.Equal(1, source.Take(1).ToList().Single()); Assert.Empty(source.Take(0).ToList()); Assert.Empty(source.Take(-10).ToList()); + + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(0..5).ToList()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(0..6).ToList()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(0..40).ToList()); + Assert.Equal(new[] { 1, 2, 3, 4 }, source.Take(0..4).ToList()); + Assert.Equal(1, source.Take(0..1).ToList().Single()); + Assert.Empty(source.Take(0..0).ToList()); + + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(^5..5).ToList()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(^5..6).ToList()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(^5..40).ToList()); + Assert.Equal(new[] { 1, 2, 3, 4 }, source.Take(^5..4).ToList()); + Assert.Equal(1, source.Take(^5..1).ToList().Single()); + Assert.Empty(source.Take(^5..0).ToList()); + Assert.Empty(source.Take(^15..0).ToList()); + + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(0..^0).ToList()); + Assert.Equal(new[] { 1, 2, 3, 4 }, source.Take(0..^1).ToList()); + Assert.Equal(1, source.Take(0..^4).ToList().Single()); + Assert.Empty(source.Take(0..^5).ToList()); + Assert.Empty(source.Take(0..^15).ToList()); + + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(^5..^0).ToList()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(^6..^0).ToList()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(^45..^0).ToList()); + Assert.Equal(new[] { 1, 2, 3, 4 }, source.Take(^5..^1).ToList()); + Assert.Equal(1, source.Take(^5..^4).ToList().Single()); + Assert.Empty(source.Take(^5..^5).ToList()); + Assert.Empty(source.Take(^15..^5).ToList()); } [Fact] @@ -431,44 +986,112 @@ public void TakeCanOnlyBeOneList() Assert.Equal(new[] { 4 }, source.Skip(1).Take(1)); Assert.Equal(new[] { 6 }, source.Take(3).Skip(2)); Assert.Equal(new[] { 2 }, source.Take(3).Take(1)); + + Assert.Equal(new[] { 2 }, source.Take(0..1)); + Assert.Equal(new[] { 4 }, source.Skip(1).Take(0..1)); + Assert.Equal(new[] { 6 }, source.Take(0..3).Skip(2)); + Assert.Equal(new[] { 2 }, source.Take(0..3).Take(0..1)); + + Assert.Equal(new[] { 2 }, source.Take(^5..1)); + Assert.Equal(new[] { 4 }, source.Skip(1).Take(^4..1)); + Assert.Equal(new[] { 6 }, source.Take(^5..3).Skip(2)); + Assert.Equal(new[] { 2 }, source.Take(^5..3).Take(^4..1)); + + Assert.Equal(new[] { 2 }, source.Take(0..^4)); + Assert.Equal(new[] { 4 }, source.Skip(1).Take(0..^3)); + Assert.Equal(new[] { 6 }, source.Take(0..^2).Skip(2)); + Assert.Equal(new[] { 2 }, source.Take(0..^2).Take(0..^2)); + + Assert.Equal(new[] { 2 }, source.Take(^5..^4)); + Assert.Equal(new[] { 4 }, source.Skip(1).Take(^4..^3)); + Assert.Equal(new[] { 6 }, source.Take(^5..^2).Skip(2)); + Assert.Equal(new[] { 2 }, source.Take(^5..^2).Take(^4..^2)); } [Fact] public void TakeCanOnlyBeOneNotList() { - var source = GuaranteeNotIList(new[] { 2, 4, 6, 8, 10 }); + var source = ForceNotCollection(new[] { 2, 4, 6, 8, 10 }); Assert.Equal(new[] { 2 }, source.Take(1)); Assert.Equal(new[] { 4 }, source.Skip(1).Take(1)); Assert.Equal(new[] { 6 }, source.Take(3).Skip(2)); Assert.Equal(new[] { 2 }, source.Take(3).Take(1)); + + Assert.Equal(new[] { 2 }, source.Take(0..1)); + Assert.Equal(new[] { 4 }, source.Skip(1).Take(0..1)); + Assert.Equal(new[] { 6 }, source.Take(0..3).Skip(2)); + Assert.Equal(new[] { 2 }, source.Take(0..3).Take(0..1)); + + Assert.Equal(new[] { 2 }, source.Take(^5..1)); + Assert.Equal(new[] { 4 }, source.Skip(1).Take(^4..1)); + Assert.Equal(new[] { 6 }, source.Take(^5..3).Skip(2)); + Assert.Equal(new[] { 2 }, source.Take(^5..3).Take(^4..1)); + + Assert.Equal(new[] { 2 }, source.Take(0..^4)); + Assert.Equal(new[] { 4 }, source.Skip(1).Take(0..^3)); + Assert.Equal(new[] { 6 }, source.Take(0..^2).Skip(2)); + Assert.Equal(new[] { 2 }, source.Take(0..^2).Take(0..^2)); + + Assert.Equal(new[] { 2 }, source.Take(^5..^4)); + Assert.Equal(new[] { 4 }, source.Skip(1).Take(^4..^3)); + Assert.Equal(new[] { 6 }, source.Take(^5..^2).Skip(2)); + Assert.Equal(new[] { 2 }, source.Take(^5..^2).Take(^4..^2)); } [Fact] public void RepeatEnumerating() { var source = new[] { 1, 2, 3, 4, 5 }; - var taken = source.Take(3); - Assert.Equal(taken, taken); + var taken1 = source.Take(3); + Assert.Equal(taken1, taken1); + + var taken2 = source.Take(0..3); + Assert.Equal(taken2, taken2); + + var taken3 = source.Take(^5..3); + Assert.Equal(taken3, taken3); + + var taken4 = source.Take(0..^2); + Assert.Equal(taken4, taken4); + + var taken5 = source.Take(^5..^2); + Assert.Equal(taken5, taken5); } [Fact] public void RepeatEnumeratingNotList() { - var source = GuaranteeNotIList(new[] { 1, 2, 3, 4, 5 }); - var taken = source.Take(3); - Assert.Equal(taken, taken); + var source = ForceNotCollection(new[] { 1, 2, 3, 4, 5 }); + var taken1 = source.Take(3); + Assert.Equal(taken1, taken1); + + var taken2 = source.Take(0..3); + Assert.Equal(taken2, taken2); + + var taken3 = source.Take(^5..3); + Assert.Equal(taken3, taken3); + + var taken4 = source.Take(0..^2); + Assert.Equal(taken4, taken4); + + var taken5 = source.Take(^5..^2); + Assert.Equal(taken5, taken5); } [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsSpeedOptimized))] [InlineData(1000)] [InlineData(1000000)] [InlineData(int.MaxValue)] - [SkipOnTargetFramework(~TargetFrameworkMonikers.Netcoreapp, ".NET Core optimizes Take(...).Skip(...) on lazy sequences to avoid unecessary allocation. Without this optimization this test takes many minutes. See https://github.com/dotnet/corefx/pull/13628.")] + [SkipOnTargetFramework(~TargetFrameworkMonikers.Netcoreapp, ".NET Core optimizes Take(...).Skip(...) on lazy sequences to avoid unnecessary allocation. Without this optimization this test takes many minutes. See https://github.com/dotnet/corefx/pull/13628.")] public void LazySkipAllTakenForLargeNumbers(int largeNumber) { Assert.Empty(new FastInfiniteEnumerator().Take(largeNumber).Skip(largeNumber)); Assert.Empty(new FastInfiniteEnumerator().Take(largeNumber).Skip(largeNumber).Skip(42)); Assert.Empty(new FastInfiniteEnumerator().Take(largeNumber).Skip(largeNumber / 2).Skip(largeNumber / 2 + 1)); + + Assert.Empty(new FastInfiniteEnumerator().Take(0..largeNumber).Skip(largeNumber)); + Assert.Empty(new FastInfiniteEnumerator().Take(0..largeNumber).Skip(largeNumber).Skip(42)); + Assert.Empty(new FastInfiniteEnumerator().Take(0..largeNumber).Skip(largeNumber / 2).Skip(largeNumber / 2 + 1)); } [Fact] @@ -476,11 +1099,35 @@ public void LazyOverflowRegression() { var range = NumberRangeGuaranteedNotCollectionType(1, 100); var skipped = range.Skip(42); // Min index is 42. - var taken = skipped.Take(int.MaxValue); // May try to calculate max index as 42 + int.MaxValue, leading to integer overflow. - Assert.Equal(Enumerable.Range(43, 100 - 42), taken); - Assert.Equal(100 - 42, taken.Count()); - Assert.Equal(Enumerable.Range(43, 100 - 42), taken.ToArray()); - Assert.Equal(Enumerable.Range(43, 100 - 42), taken.ToList()); + var taken1 = skipped.Take(int.MaxValue); // May try to calculate max index as 42 + int.MaxValue, leading to integer overflow. + Assert.Equal(Enumerable.Range(43, 100 - 42), taken1); + Assert.Equal(100 - 42, taken1.Count()); + Assert.Equal(Enumerable.Range(43, 100 - 42), taken1.ToArray()); + Assert.Equal(Enumerable.Range(43, 100 - 42), taken1.ToList()); + + var taken2 = NumberRangeGuaranteedNotCollectionType(1, 100).Take(42..int.MaxValue); + Assert.Equal(Enumerable.Range(43, 100 - 42), taken2); + Assert.Equal(100 - 42, taken2.Count()); + Assert.Equal(Enumerable.Range(43, 100 - 42), taken2.ToArray()); + Assert.Equal(Enumerable.Range(43, 100 - 42), taken2.ToList()); + + var taken3 = NumberRangeGuaranteedNotCollectionType(1, 100).Take(^(100 - 42)..int.MaxValue); + Assert.Equal(Enumerable.Range(43, 100 - 42), taken3); + Assert.Equal(100 - 42, taken3.Count()); + Assert.Equal(Enumerable.Range(43, 100 - 42), taken3.ToArray()); + Assert.Equal(Enumerable.Range(43, 100 - 42), taken3.ToList()); + + var taken4 = NumberRangeGuaranteedNotCollectionType(1, 100).Take(42..^0); + Assert.Equal(Enumerable.Range(43, 100 - 42), taken4); + Assert.Equal(100 - 42, taken4.Count()); + Assert.Equal(Enumerable.Range(43, 100 - 42), taken4.ToArray()); + Assert.Equal(Enumerable.Range(43, 100 - 42), taken4.ToList()); + + var taken5 = NumberRangeGuaranteedNotCollectionType(1, 100).Take(^(100 - 42)..^0); + Assert.Equal(Enumerable.Range(43, 100 - 42), taken5); + Assert.Equal(100 - 42, taken5.Count()); + Assert.Equal(Enumerable.Range(43, 100 - 42), taken5.ToArray()); + Assert.Equal(Enumerable.Range(43, 100 - 42), taken5.ToList()); } [Theory] @@ -496,10 +1143,41 @@ public void LazyOverflowRegression() [InlineData(10, 100, 90)] public void CountOfLazySkipTakeChain(int skip, int take, int expected) { - var partition = NumberRangeGuaranteedNotCollectionType(1, 100).Skip(skip).Take(take); - Assert.Equal(expected, partition.Count()); - Assert.Equal(expected, partition.Select(i => i).Count()); - Assert.Equal(expected, partition.Select(i => i).ToArray().Length); + int totalCount = 100; + var partition1 = NumberRangeGuaranteedNotCollectionType(1, totalCount).Skip(skip).Take(take); + Assert.Equal(expected, partition1.Count()); + Assert.Equal(expected, partition1.Select(i => i).Count()); + Assert.Equal(expected, partition1.Select(i => i).ToArray().Length); + + int end; + try + { + end = checked(skip + take); + } + catch (OverflowException) + { + end = int.MaxValue; + } + + var partition2 = NumberRangeGuaranteedNotCollectionType(1, totalCount).Take(skip..end); + Assert.Equal(expected, partition2.Count()); + Assert.Equal(expected, partition2.Select(i => i).Count()); + Assert.Equal(expected, partition2.Select(i => i).ToArray().Length); + + var partition3 = NumberRangeGuaranteedNotCollectionType(1, totalCount).Take(^Math.Max(totalCount - skip, 0)..end); + Assert.Equal(expected, partition3.Count()); + Assert.Equal(expected, partition3.Select(i => i).Count()); + Assert.Equal(expected, partition3.Select(i => i).ToArray().Length); + + var partition4 = NumberRangeGuaranteedNotCollectionType(1, totalCount).Take(skip..^Math.Max(totalCount - end, 0)); + Assert.Equal(expected, partition4.Count()); + Assert.Equal(expected, partition4.Select(i => i).Count()); + Assert.Equal(expected, partition4.Select(i => i).ToArray().Length); + + var partition5 = NumberRangeGuaranteedNotCollectionType(1, totalCount).Take(^Math.Max(totalCount - skip, 0)..^Math.Max(totalCount - end, 0)); + Assert.Equal(expected, partition5.Count()); + Assert.Equal(expected, partition5.Select(i => i).Count()); + Assert.Equal(expected, partition5.Select(i => i).ToArray().Length); } [Theory] @@ -509,14 +1187,52 @@ public void CountOfLazySkipTakeChain(int skip, int take, int expected) [InlineData(new[] { 1, 2, 3, 5, 8, 13 }, 0, 2, 1, 2)] [InlineData(new[] { 1, 2, 3, 5, 8, 13 }, 500, 2, 0, 0)] [InlineData(new int[] { }, 10, 8, 0, 0)] - public void FirstAndLastOfLazySkipTakeChain(IEnumerable source, int skip, int take, int first, int last) + public void FirstAndLastOfLazySkipTakeChain(int[] source, int skip, int take, int first, int last) { - var partition = ForceNotCollection(source).Skip(skip).Take(take); + var partition1 = ForceNotCollection(source).Skip(skip).Take(take); + + Assert.Equal(first, partition1.FirstOrDefault()); + Assert.Equal(first, partition1.ElementAtOrDefault(0)); + Assert.Equal(last, partition1.LastOrDefault()); + Assert.Equal(last, partition1.ElementAtOrDefault(partition1.Count() - 1)); - Assert.Equal(first, partition.FirstOrDefault()); - Assert.Equal(first, partition.ElementAtOrDefault(0)); - Assert.Equal(last, partition.LastOrDefault()); - Assert.Equal(last, partition.ElementAtOrDefault(partition.Count() - 1)); + int end; + try + { + end = checked(skip + take); + } + catch (OverflowException) + { + end = int.MaxValue; + } + + var partition2 = ForceNotCollection(source).Take(skip..end); + + Assert.Equal(first, partition2.FirstOrDefault()); + Assert.Equal(first, partition2.ElementAtOrDefault(0)); + Assert.Equal(last, partition2.LastOrDefault()); + Assert.Equal(last, partition2.ElementAtOrDefault(partition2.Count() - 1)); + + var partition3 = ForceNotCollection(source).Take(^Math.Max(source.Length - skip, 0)..end); + + Assert.Equal(first, partition3.FirstOrDefault()); + Assert.Equal(first, partition3.ElementAtOrDefault(0)); + Assert.Equal(last, partition3.LastOrDefault()); + Assert.Equal(last, partition3.ElementAtOrDefault(partition3.Count() - 1)); + + var partition4 = ForceNotCollection(source).Take(skip..^Math.Max(source.Length - end, 0)); + + Assert.Equal(first, partition4.FirstOrDefault()); + Assert.Equal(first, partition4.ElementAtOrDefault(0)); + Assert.Equal(last, partition4.LastOrDefault()); + Assert.Equal(last, partition4.ElementAtOrDefault(partition4.Count() - 1)); + + var partition5 = ForceNotCollection(source).Take(^Math.Max(source.Length - skip, 0)..^Math.Max(source.Length - end, 0)); + + Assert.Equal(first, partition5.FirstOrDefault()); + Assert.Equal(first, partition5.ElementAtOrDefault(0)); + Assert.Equal(last, partition5.LastOrDefault()); + Assert.Equal(last, partition5.ElementAtOrDefault(partition5.Count() - 1)); } [Theory] @@ -524,14 +1240,48 @@ public void FirstAndLastOfLazySkipTakeChain(IEnumerable source, int skip, i [InlineData(new[] { 0xfefe, 7000, 123 }, 0, 3, new[] { -1, 0, 1, 2 }, new[] { 0, 0xfefe, 7000, 123 })] [InlineData(new[] { 0xfefe }, 100, 100, new[] { -1, 0, 1, 2 }, new[] { 0, 0, 0, 0 })] [InlineData(new[] { 0xfefe, 123, 456, 7890, 5555, 55 }, 1, 10, new[] { -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }, new[] { 0, 123, 456, 7890, 5555, 55, 0, 0, 0, 0, 0, 0, 0 })] - public void ElementAtOfLazySkipTakeChain(IEnumerable source, int skip, int take, int[] indices, int[] expectedValues) + public void ElementAtOfLazySkipTakeChain(int[] source, int skip, int take, int[] indices, int[] expectedValues) { - var partition = ForceNotCollection(source).Skip(skip).Take(take); + var partition1 = ForceNotCollection(source).Skip(skip).Take(take); Assert.Equal(indices.Length, expectedValues.Length); for (int i = 0; i < indices.Length; i++) { - Assert.Equal(expectedValues[i], partition.ElementAtOrDefault(indices[i])); + Assert.Equal(expectedValues[i], partition1.ElementAtOrDefault(indices[i])); + } + + int end; + try + { + end = checked(skip + take); + } + catch (OverflowException) + { + end = int.MaxValue; + } + + var partition2 = ForceNotCollection(source).Take(skip..end); + for (int i = 0; i < indices.Length; i++) + { + Assert.Equal(expectedValues[i], partition2.ElementAtOrDefault(indices[i])); + } + + var partition3 = ForceNotCollection(source).Take(^Math.Max(source.Length - skip, 0)..end); + for (int i = 0; i < indices.Length; i++) + { + Assert.Equal(expectedValues[i], partition3.ElementAtOrDefault(indices[i])); + } + + var partition4 = ForceNotCollection(source).Take(skip..^Math.Max(source.Length - end, 0)); + for (int i = 0; i < indices.Length; i++) + { + Assert.Equal(expectedValues[i], partition4.ElementAtOrDefault(indices[i])); + } + + var partition5 = ForceNotCollection(source).Take(^Math.Max(source.Length - skip, 0)..^Math.Max(source.Length - end, 0)); + for (int i = 0; i < indices.Length; i++) + { + Assert.Equal(expectedValues[i], partition5.ElementAtOrDefault(indices[i])); } } @@ -544,24 +1294,701 @@ public void ElementAtOfLazySkipTakeChain(IEnumerable source, int skip, int [InlineData(2, 3)] public void DisposeSource(int sourceCount, int count) { - int state = 0; + bool[] isIteratorDisposed = new bool[5]; - var source = new DelegateIterator( - moveNext: () => ++state <= sourceCount, - current: () => 0, - dispose: () => state = -1); + var source = Repeat( + index => + { + int state = 0; + return new DelegateIterator( + moveNext: () => ++state <= sourceCount, + current: () => 0, + dispose: () => { state = -1; isIteratorDisposed[index] = true; }); + }, + 5); - IEnumerator iterator = source.Take(count).GetEnumerator(); - int iteratorCount = Math.Min(sourceCount, Math.Max(0, count)); - Assert.All(Enumerable.Range(0, iteratorCount), _ => Assert.True(iterator.MoveNext())); + IEnumerator iterator0 = source[0].Take(count).GetEnumerator(); + int iteratorCount0 = Math.Min(sourceCount, Math.Max(0, count)); + Assert.All(Enumerable.Range(0, iteratorCount0), _ => Assert.True(iterator0.MoveNext())); - Assert.False(iterator.MoveNext()); + Assert.False(iterator0.MoveNext()); // Unlike Skip, Take can tell straightaway that it can return a sequence with no elements if count <= 0. // The enumerable it returns is a specialized empty iterator that has no connections to the source. Hence, // after MoveNext returns false under those circumstances, it won't invoke Dispose on our enumerator. - int expected = count <= 0 ? 0 : -1; - Assert.Equal(expected, state); + bool isItertorNotEmpty0 = count > 0; + Assert.Equal(isItertorNotEmpty0, isIteratorDisposed[0]); + + int end = Math.Max(0, count); + IEnumerator iterator1 = source[1].Take(0..end).GetEnumerator(); + Assert.All(Enumerable.Range(0, Math.Min(sourceCount, Math.Max(0, count))), _ => Assert.True(iterator1.MoveNext())); + Assert.False(iterator1.MoveNext()); + // When startIndex end and endIndex are both not from end and startIndex >= endIndex, Take(Range) returns an empty array. + bool isItertorNotEmpty1 = end != 0; + Assert.Equal(isItertorNotEmpty1, isIteratorDisposed[1]); + + int startIndexFromEnd = Math.Max(sourceCount, end); + int endIndexFromEnd = Math.Max(0, sourceCount - end); + + IEnumerator iterator2 = source[2].Take(^startIndexFromEnd..end).GetEnumerator(); + Assert.All(Enumerable.Range(0, Math.Min(sourceCount, Math.Max(0, count))), _ => Assert.True(iterator2.MoveNext())); + Assert.False(iterator2.MoveNext()); + // When startIndex is ^0, Take(Range) returns an empty array. + bool isItertorNotEmpty2 = startIndexFromEnd != 0; + Assert.Equal(isItertorNotEmpty2, isIteratorDisposed[2]); + + IEnumerator iterator3 = source[3].Take(0..^endIndexFromEnd).GetEnumerator(); + Assert.All(Enumerable.Range(0, Math.Min(sourceCount, Math.Max(0, count))), _ => Assert.True(iterator3.MoveNext())); + Assert.False(iterator3.MoveNext()); + Assert.True(isIteratorDisposed[3]); + + IEnumerator iterator4 = source[4].Take(^startIndexFromEnd..^endIndexFromEnd).GetEnumerator(); + Assert.All(Enumerable.Range(0, Math.Min(sourceCount, Math.Max(0, count))), _ => Assert.True(iterator4.MoveNext())); + Assert.False(iterator4.MoveNext()); + // When startIndex is ^0, + // or when startIndex and endIndex are both from end and startIndex <= endIndexFromEnd, Take(Range) returns an empty array. + bool isItertorNotEmpty4 = startIndexFromEnd != 0 && startIndexFromEnd > endIndexFromEnd; + Assert.Equal(isItertorNotEmpty4, isIteratorDisposed[4]); + } + + [Fact] + public void OutOfBoundNoException() + { + Func source = () => new[] { 1, 2, 3, 4, 5 }; + + Assert.Equal(source(), source().Take(0..6)); + Assert.Equal(source(), source().Take(0..int.MaxValue)); + + Assert.Equal(new int[] { 1, 2, 3, 4 }, source().Take(^10..4)); + Assert.Equal(new int[] { 1, 2, 3, 4 }, source().Take(^int.MaxValue..4)); + Assert.Equal(source(), source().Take(^10..6)); + Assert.Equal(source(), source().Take(^int.MaxValue..6)); + Assert.Equal(source(), source().Take(^10..int.MaxValue)); + Assert.Equal(source(), source().Take(^int.MaxValue..int.MaxValue)); + + Assert.Empty(source().Take(0..^6)); + Assert.Empty(source().Take(0..^int.MaxValue)); + Assert.Empty(source().Take(4..^6)); + Assert.Empty(source().Take(4..^int.MaxValue)); + Assert.Empty(source().Take(6..^6)); + Assert.Empty(source().Take(6..^int.MaxValue)); + Assert.Empty(source().Take(int.MaxValue..^6)); + Assert.Empty(source().Take(int.MaxValue..^int.MaxValue)); + + Assert.Equal(new int[] { 1, 2, 3, 4 }, source().Take(^10..^1)); + Assert.Equal(new int[] { 1, 2, 3, 4 }, source().Take(^int.MaxValue..^1)); + Assert.Empty(source().Take(^0..^6)); + Assert.Empty(source().Take(^1..^6)); + Assert.Empty(source().Take(^6..^6)); + Assert.Empty(source().Take(^10..^6)); + Assert.Empty(source().Take(^int.MaxValue..^6)); + Assert.Empty(source().Take(^0..^int.MaxValue)); + Assert.Empty(source().Take(^1..^int.MaxValue)); + Assert.Empty(source().Take(^6..^int.MaxValue)); + Assert.Empty(source().Take(^int.MaxValue..^int.MaxValue)); + } + + [Fact] + public void OutOfBoundNoExceptionNotList() + { + var source = new[] { 1, 2, 3, 4, 5 }; + + Assert.Equal(source, ForceNotCollection(source).Take(0..6)); + Assert.Equal(source, ForceNotCollection(source).Take(0..int.MaxValue)); + + Assert.Equal(new int[] { 1, 2, 3, 4 }, ForceNotCollection(source).Take(^10..4)); + Assert.Equal(new int[] { 1, 2, 3, 4 }, ForceNotCollection(source).Take(^int.MaxValue..4)); + Assert.Equal(source, ForceNotCollection(source).Take(^10..6)); + Assert.Equal(source, ForceNotCollection(source).Take(^int.MaxValue..6)); + Assert.Equal(source, ForceNotCollection(source).Take(^10..int.MaxValue)); + Assert.Equal(source, ForceNotCollection(source).Take(^int.MaxValue..int.MaxValue)); + + Assert.Empty(ForceNotCollection(source).Take(0..^6)); + Assert.Empty(ForceNotCollection(source).Take(0..^int.MaxValue)); + Assert.Empty(ForceNotCollection(source).Take(4..^6)); + Assert.Empty(ForceNotCollection(source).Take(4..^int.MaxValue)); + Assert.Empty(ForceNotCollection(source).Take(6..^6)); + Assert.Empty(ForceNotCollection(source).Take(6..^int.MaxValue)); + Assert.Empty(ForceNotCollection(source).Take(int.MaxValue..^6)); + Assert.Empty(ForceNotCollection(source).Take(int.MaxValue..^int.MaxValue)); + + Assert.Equal(new int[] { 1, 2, 3, 4 }, ForceNotCollection(source).Take(^10..^1)); + Assert.Equal(new int[] { 1, 2, 3, 4 }, ForceNotCollection(source).Take(^int.MaxValue..^1)); + Assert.Empty(ForceNotCollection(source).Take(^0..^6)); + Assert.Empty(ForceNotCollection(source).Take(^1..^6)); + Assert.Empty(ForceNotCollection(source).Take(^6..^6)); + Assert.Empty(ForceNotCollection(source).Take(^10..^6)); + Assert.Empty(ForceNotCollection(source).Take(^int.MaxValue..^6)); + Assert.Empty(ForceNotCollection(source).Take(^0..^int.MaxValue)); + Assert.Empty(ForceNotCollection(source).Take(^1..^int.MaxValue)); + Assert.Empty(ForceNotCollection(source).Take(^6..^int.MaxValue)); + Assert.Empty(ForceNotCollection(source).Take(^int.MaxValue..^int.MaxValue)); + } + + [Fact] + public void OutOfBoundNoExceptionListPartition() + { + var source = new[] { 1, 2, 3, 4, 5 }; + + Assert.Equal(source, ListPartitionOrEmpty(source).Take(0..6)); + Assert.Equal(source, ListPartitionOrEmpty(source).Take(0..int.MaxValue)); + + Assert.Equal(new int[] { 1, 2, 3, 4 }, ListPartitionOrEmpty(source).Take(^10..4)); + Assert.Equal(new int[] { 1, 2, 3, 4 }, ListPartitionOrEmpty(source).Take(^int.MaxValue..4)); + Assert.Equal(source, ListPartitionOrEmpty(source).Take(^10..6)); + Assert.Equal(source, ListPartitionOrEmpty(source).Take(^int.MaxValue..6)); + Assert.Equal(source, ListPartitionOrEmpty(source).Take(^10..int.MaxValue)); + Assert.Equal(source, ListPartitionOrEmpty(source).Take(^int.MaxValue..int.MaxValue)); + + Assert.Empty(ListPartitionOrEmpty(source).Take(0..^6)); + Assert.Empty(ListPartitionOrEmpty(source).Take(0..^int.MaxValue)); + Assert.Empty(ListPartitionOrEmpty(source).Take(4..^6)); + Assert.Empty(ListPartitionOrEmpty(source).Take(4..^int.MaxValue)); + Assert.Empty(ListPartitionOrEmpty(source).Take(6..^6)); + Assert.Empty(ListPartitionOrEmpty(source).Take(6..^int.MaxValue)); + Assert.Empty(ListPartitionOrEmpty(source).Take(int.MaxValue..^6)); + Assert.Empty(ListPartitionOrEmpty(source).Take(int.MaxValue..^int.MaxValue)); + + Assert.Equal(new int[] { 1, 2, 3, 4 }, ListPartitionOrEmpty(source).Take(^10..^1)); + Assert.Equal(new int[] { 1, 2, 3, 4 }, ListPartitionOrEmpty(source).Take(^int.MaxValue..^1)); + Assert.Empty(ListPartitionOrEmpty(source).Take(^0..^6)); + Assert.Empty(ListPartitionOrEmpty(source).Take(^1..^6)); + Assert.Empty(ListPartitionOrEmpty(source).Take(^6..^6)); + Assert.Empty(ListPartitionOrEmpty(source).Take(^10..^6)); + Assert.Empty(ListPartitionOrEmpty(source).Take(^int.MaxValue..^6)); + Assert.Empty(ListPartitionOrEmpty(source).Take(^0..^int.MaxValue)); + Assert.Empty(ListPartitionOrEmpty(source).Take(^1..^int.MaxValue)); + Assert.Empty(ListPartitionOrEmpty(source).Take(^6..^int.MaxValue)); + Assert.Empty(ListPartitionOrEmpty(source).Take(^int.MaxValue..^int.MaxValue)); + } + + [Fact] + public void OutOfBoundNoExceptionEnumerablePartition() + { + var source = new[] { 1, 2, 3, 4, 5 }; + + Assert.Equal(source, EnumerablePartitionOrEmpty(source).Take(0..6)); + Assert.Equal(source, EnumerablePartitionOrEmpty(source).Take(0..int.MaxValue)); + + Assert.Equal(new int[] { 1, 2, 3, 4 }, EnumerablePartitionOrEmpty(source).Take(^10..4)); + Assert.Equal(new int[] { 1, 2, 3, 4 }, EnumerablePartitionOrEmpty(source).Take(^int.MaxValue..4)); + Assert.Equal(source, EnumerablePartitionOrEmpty(source).Take(^10..6)); + Assert.Equal(source, EnumerablePartitionOrEmpty(source).Take(^int.MaxValue..6)); + Assert.Equal(source, EnumerablePartitionOrEmpty(source).Take(^10..int.MaxValue)); + Assert.Equal(source, EnumerablePartitionOrEmpty(source).Take(^int.MaxValue..int.MaxValue)); + + Assert.Empty(EnumerablePartitionOrEmpty(source).Take(0..^6)); + Assert.Empty(EnumerablePartitionOrEmpty(source).Take(0..^int.MaxValue)); + Assert.Empty(EnumerablePartitionOrEmpty(source).Take(4..^6)); + Assert.Empty(EnumerablePartitionOrEmpty(source).Take(4..^int.MaxValue)); + Assert.Empty(EnumerablePartitionOrEmpty(source).Take(6..^6)); + Assert.Empty(EnumerablePartitionOrEmpty(source).Take(6..^int.MaxValue)); + Assert.Empty(EnumerablePartitionOrEmpty(source).Take(int.MaxValue..^6)); + Assert.Empty(EnumerablePartitionOrEmpty(source).Take(int.MaxValue..^int.MaxValue)); + + Assert.Equal(new int[] { 1, 2, 3, 4 }, EnumerablePartitionOrEmpty(source).Take(^10..^1)); + Assert.Equal(new int[] { 1, 2, 3, 4 }, EnumerablePartitionOrEmpty(source).Take(^int.MaxValue..^1)); + Assert.Empty(EnumerablePartitionOrEmpty(source).Take(^0..^6)); + Assert.Empty(EnumerablePartitionOrEmpty(source).Take(^1..^6)); + Assert.Empty(EnumerablePartitionOrEmpty(source).Take(^6..^6)); + Assert.Empty(EnumerablePartitionOrEmpty(source).Take(^10..^6)); + Assert.Empty(EnumerablePartitionOrEmpty(source).Take(^int.MaxValue..^6)); + Assert.Empty(EnumerablePartitionOrEmpty(source).Take(^0..^int.MaxValue)); + Assert.Empty(EnumerablePartitionOrEmpty(source).Take(^1..^int.MaxValue)); + Assert.Empty(EnumerablePartitionOrEmpty(source).Take(^6..^int.MaxValue)); + Assert.Empty(EnumerablePartitionOrEmpty(source).Take(^int.MaxValue..^int.MaxValue)); + } + + [Fact] + public void MutableSource() + { + var source1 = new List() { 0, 1, 2, 3, 4 }; + var query1 = source1.Take(3); + source1.RemoveAt(0); + source1.InsertRange(2, new[] { -1, -2 }); + Assert.Equal(new[] { 1, 2, -1 }, query1); + + var source2 = new List() { 0, 1, 2, 3, 4 }; + var query2 = source2.Take(0..3); + source2.RemoveAt(0); + source2.InsertRange(2, new[] { -1, -2 }); + Assert.Equal(new[] { 1, 2, -1 }, query2); + + var source3 = new List() { 0, 1, 2, 3, 4 }; + var query3 = source3.Take(^6..3); + source3.RemoveAt(0); + source3.InsertRange(2, new[] { -1, -2 }); + Assert.Equal(new[] { 1, 2, -1 }, query3); + + var source4 = new List() { 0, 1, 2, 3, 4 }; + var query4 = source4.Take(^6..^3); + source4.RemoveAt(0); + source4.InsertRange(2, new[] { -1, -2 }); + Assert.Equal(new[] { 1, 2, -1 }, query4); + } + + [Fact] + public void MutableSourceNotList() + { + var source1 = new List() { 0, 1, 2, 3, 4 }; + var query1 = ForceNotCollection(source1).Select(i => i).Take(3); + source1.RemoveAt(0); + source1.InsertRange(2, new[] { -1, -2 }); + Assert.Equal(new[] { 1, 2, -1 }, query1); + + var source2 = new List() { 0, 1, 2, 3, 4 }; + var query2 = ForceNotCollection(source2).Select(i => i).Take(0..3); + source2.RemoveAt(0); + source2.InsertRange(2, new[] { -1, -2 }); + Assert.Equal(new[] { 1, 2, -1 }, query2); + + var source3 = new List() { 0, 1, 2, 3, 4 }; + var query3 = ForceNotCollection(source3).Select(i => i).Take(^6..3); + source3.RemoveAt(0); + source3.InsertRange(2, new[] { -1, -2 }); + Assert.Equal(new[] { 1, 2, -1 }, query3); + + var source4 = new List() { 0, 1, 2, 3, 4 }; + var query4 = ForceNotCollection(source4).Select(i => i).Take(^6..^3); + source4.RemoveAt(0); + source4.InsertRange(2, new[] { -1, -2 }); + Assert.Equal(new[] { 1, 2, -1 }, query4); + } + + [Fact] + public void NonEmptySource_ConsistencyWithCountable() + { + Func source = () => new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + + // Multiple elements in the middle. + Assert.Equal(source()[^9..5], source().Take(^9..5)); + Assert.Equal(source()[2..7], source().Take(2..7)); + Assert.Equal(source()[2..^4], source().Take(2..^4)); + Assert.Equal(source()[^7..^4], source().Take(^7..^4)); + + // Range with default index. + Assert.Equal(source()[^9..], source().Take(^9..)); + Assert.Equal(source()[2..], source().Take(2..)); + Assert.Equal(source()[..^4], source().Take(..^4)); + Assert.Equal(source()[..6], source().Take(..6)); + + // All. + Assert.Equal(source()[..], source().Take(..)); + + // Single element in the middle. + Assert.Equal(source()[^9..2], source().Take(^9..2)); + Assert.Equal(source()[2..3], source().Take(2..3)); + Assert.Equal(source()[2..^7], source().Take(2..^7)); + Assert.Equal(source()[^5..^4], source().Take(^5..^4)); + + // Single element at start. + Assert.Equal(source()[^10..1], source().Take(^10..1)); + Assert.Equal(source()[0..1], source().Take(0..1)); + Assert.Equal(source()[0..^9], source().Take(0..^9)); + Assert.Equal(source()[^10..^9], source().Take(^10..^9)); + + // Single element at end. + Assert.Equal(source()[^1..10], source().Take(^1..10)); + Assert.Equal(source()[9..10], source().Take(9..10)); + Assert.Equal(source()[9..^0], source().Take(9..^0)); + Assert.Equal(source()[^1..^0], source().Take(^1..^0)); + + // No element. + Assert.Equal(source()[3..3], source().Take(3..3)); + Assert.Equal(source()[6..^4], source().Take(6..^4)); + Assert.Equal(source()[3..^7], source().Take(3..^7)); + Assert.Equal(source()[^3..7], source().Take(^3..7)); + Assert.Equal(source()[^6..^6], source().Take(^6..^6)); + } + + [Fact] + public void NonEmptySource_ConsistencyWithCountable_NotList() + { + int[] source = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + + // Multiple elements in the middle. + Assert.Equal(source[^9..5], ForceNotCollection(source).Take(^9..5)); + Assert.Equal(source[2..7], ForceNotCollection(source).Take(2..7)); + Assert.Equal(source[2..^4], ForceNotCollection(source).Take(2..^4)); + Assert.Equal(source[^7..^4], ForceNotCollection(source).Take(^7..^4)); + + // Range with default index. + Assert.Equal(source[^9..], ForceNotCollection(source).Take(^9..)); + Assert.Equal(source[2..], ForceNotCollection(source).Take(2..)); + Assert.Equal(source[..^4], ForceNotCollection(source).Take(..^4)); + Assert.Equal(source[..6], ForceNotCollection(source).Take(..6)); + + // All. + Assert.Equal(source[..], ForceNotCollection(source).Take(..)); + + // Single element in the middle. + Assert.Equal(source[^9..2], ForceNotCollection(source).Take(^9..2)); + Assert.Equal(source[2..3], ForceNotCollection(source).Take(2..3)); + Assert.Equal(source[2..^7], ForceNotCollection(source).Take(2..^7)); + Assert.Equal(source[^5..^4], ForceNotCollection(source).Take(^5..^4)); + + // Single element at start. + Assert.Equal(source[^10..1], ForceNotCollection(source).Take(^10..1)); + Assert.Equal(source[0..1], ForceNotCollection(source).Take(0..1)); + Assert.Equal(source[0..^9], ForceNotCollection(source).Take(0..^9)); + Assert.Equal(source[^10..^9], ForceNotCollection(source).Take(^10..^9)); + + // Single element at end. + Assert.Equal(source[^1..10], ForceNotCollection(source).Take(^1..10)); + Assert.Equal(source[9..10], ForceNotCollection(source).Take(9..10)); + Assert.Equal(source[9..^0], ForceNotCollection(source).Take(9..^0)); + Assert.Equal(source[^1..^0], ForceNotCollection(source).Take(^1..^0)); + + // No element. + Assert.Equal(source[3..3], ForceNotCollection(source).Take(3..3)); + Assert.Equal(source[6..^4], ForceNotCollection(source).Take(6..^4)); + Assert.Equal(source[3..^7], ForceNotCollection(source).Take(3..^7)); + Assert.Equal(source[^3..7], ForceNotCollection(source).Take(^3..7)); + Assert.Equal(source[^6..^6], ForceNotCollection(source).Take(^6..^6)); + } + + [Fact] + public void NonEmptySource_ConsistencyWithCountable_ListPartition() + { + int[] source = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + + // Multiple elements in the middle. + Assert.Equal(source[^9..5], ListPartitionOrEmpty(source).Take(^9..5)); + Assert.Equal(source[2..7], ListPartitionOrEmpty(source).Take(2..7)); + Assert.Equal(source[2..^4], ListPartitionOrEmpty(source).Take(2..^4)); + Assert.Equal(source[^7..^4], ListPartitionOrEmpty(source).Take(^7..^4)); + + // Range with default index. + Assert.Equal(source[^9..], ListPartitionOrEmpty(source).Take(^9..)); + Assert.Equal(source[2..], ListPartitionOrEmpty(source).Take(2..)); + Assert.Equal(source[..^4], ListPartitionOrEmpty(source).Take(..^4)); + Assert.Equal(source[..6], ListPartitionOrEmpty(source).Take(..6)); + + // All. + Assert.Equal(source[..], ListPartitionOrEmpty(source).Take(..)); + + // Single element in the middle. + Assert.Equal(source[^9..2], ListPartitionOrEmpty(source).Take(^9..2)); + Assert.Equal(source[2..3], ListPartitionOrEmpty(source).Take(2..3)); + Assert.Equal(source[2..^7], ListPartitionOrEmpty(source).Take(2..^7)); + Assert.Equal(source[^5..^4], ListPartitionOrEmpty(source).Take(^5..^4)); + + // Single element at start. + Assert.Equal(source[^10..1], ListPartitionOrEmpty(source).Take(^10..1)); + Assert.Equal(source[0..1], ListPartitionOrEmpty(source).Take(0..1)); + Assert.Equal(source[0..^9], ListPartitionOrEmpty(source).Take(0..^9)); + Assert.Equal(source[^10..^9], ListPartitionOrEmpty(source).Take(^10..^9)); + + // Single element at end. + Assert.Equal(source[^1..10], ListPartitionOrEmpty(source).Take(^1..10)); + Assert.Equal(source[9..10], ListPartitionOrEmpty(source).Take(9..10)); + Assert.Equal(source[9..^0], ListPartitionOrEmpty(source).Take(9..^0)); + Assert.Equal(source[^1..^0], ListPartitionOrEmpty(source).Take(^1..^0)); + + // No element. + Assert.Equal(source[3..3], ListPartitionOrEmpty(source).Take(3..3)); + Assert.Equal(source[6..^4], ListPartitionOrEmpty(source).Take(6..^4)); + Assert.Equal(source[3..^7], ListPartitionOrEmpty(source).Take(3..^7)); + Assert.Equal(source[^3..7], ListPartitionOrEmpty(source).Take(^3..7)); + Assert.Equal(source[^6..^6], ListPartitionOrEmpty(source).Take(^6..^6)); + } + + [Fact] + public void NonEmptySource_ConsistencyWithCountable_EnumerablePartition() + { + int[] source = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + + // Multiple elements in the middle. + Assert.Equal(source[^9..5], EnumerablePartitionOrEmpty(source).Take(^9..5)); + Assert.Equal(source[2..7], EnumerablePartitionOrEmpty(source).Take(2..7)); + Assert.Equal(source[2..^4], EnumerablePartitionOrEmpty(source).Take(2..^4)); + Assert.Equal(source[^7..^4], EnumerablePartitionOrEmpty(source).Take(^7..^4)); + + // Range with default index. + Assert.Equal(source[^9..], EnumerablePartitionOrEmpty(source).Take(^9..)); + Assert.Equal(source[2..], EnumerablePartitionOrEmpty(source).Take(2..)); + Assert.Equal(source[..^4], EnumerablePartitionOrEmpty(source).Take(..^4)); + Assert.Equal(source[..6], EnumerablePartitionOrEmpty(source).Take(..6)); + + // All. + Assert.Equal(source[..], EnumerablePartitionOrEmpty(source).Take(..)); + + // Single element in the middle. + Assert.Equal(source[^9..2], EnumerablePartitionOrEmpty(source).Take(^9..2)); + Assert.Equal(source[2..3], EnumerablePartitionOrEmpty(source).Take(2..3)); + Assert.Equal(source[2..^7], EnumerablePartitionOrEmpty(source).Take(2..^7)); + Assert.Equal(source[^5..^4], EnumerablePartitionOrEmpty(source).Take(^5..^4)); + + // Single element at start. + Assert.Equal(source[^10..1], EnumerablePartitionOrEmpty(source).Take(^10..1)); + Assert.Equal(source[0..1], EnumerablePartitionOrEmpty(source).Take(0..1)); + Assert.Equal(source[0..^9], EnumerablePartitionOrEmpty(source).Take(0..^9)); + Assert.Equal(source[^10..^9], EnumerablePartitionOrEmpty(source).Take(^10..^9)); + + // Single element at end. + Assert.Equal(source[^1..10], EnumerablePartitionOrEmpty(source).Take(^1..10)); + Assert.Equal(source[9..10], EnumerablePartitionOrEmpty(source).Take(9..10)); + Assert.Equal(source[9..^0], EnumerablePartitionOrEmpty(source).Take(9..^0)); + Assert.Equal(source[^1..^0], EnumerablePartitionOrEmpty(source).Take(^1..^0)); + + // No element. + Assert.Equal(source[3..3], EnumerablePartitionOrEmpty(source).Take(3..3)); + Assert.Equal(source[6..^4], EnumerablePartitionOrEmpty(source).Take(6..^4)); + Assert.Equal(source[3..^7], EnumerablePartitionOrEmpty(source).Take(3..^7)); + Assert.Equal(source[^3..7], EnumerablePartitionOrEmpty(source).Take(^3..7)); + Assert.Equal(source[^6..^6], EnumerablePartitionOrEmpty(source).Take(^6..^6)); + } + + [Fact] + public void NonEmptySource_DoNotThrowException() + { + Func source = () => new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + + Assert.Empty(source().Take(3..2)); + Assert.Empty(source().Take(6..^5)); + Assert.Empty(source().Take(3..^8)); + Assert.Empty(source().Take(^6..^7)); + } + + [Fact] + public void NonEmptySource_DoNotThrowException_NotList() + { + int[] source = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + + Assert.Empty(ForceNotCollection(source).Take(3..2)); + Assert.Empty(ForceNotCollection(source).Take(6..^5)); + Assert.Empty(ForceNotCollection(source).Take(3..^8)); + Assert.Empty(ForceNotCollection(source).Take(^6..^7)); + } + + [Fact] + public void NonEmptySource_DoNotThrowException_ListPartition() + { + int[] source = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + + Assert.Empty(ListPartitionOrEmpty(source).Take(3..2)); + Assert.Empty(ListPartitionOrEmpty(source).Take(6..^5)); + Assert.Empty(ListPartitionOrEmpty(source).Take(3..^8)); + Assert.Empty(ListPartitionOrEmpty(source).Take(^6..^7)); + } + + [Fact] + public void NonEmptySource_DoNotThrowException_EnumerablePartition() + { + int[] source = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + + Assert.Empty(EnumerablePartitionOrEmpty(source).Take(3..2)); + Assert.Empty(EnumerablePartitionOrEmpty(source).Take(6..^5)); + Assert.Empty(EnumerablePartitionOrEmpty(source).Take(3..^8)); + Assert.Empty(EnumerablePartitionOrEmpty(source).Take(^6..^7)); + } + + [Fact] + public void EmptySource_DoNotThrowException() + { + Func source = () => new int[] { }; + + // Multiple elements in the middle. + Assert.Empty(source().Take(^9..5)); + Assert.Empty(source().Take(2..7)); + Assert.Empty(source().Take(2..^4)); + Assert.Empty(source().Take(^7..^4)); + + // Range with default index. + Assert.Empty(source().Take(^9..)); + Assert.Empty(source().Take(2..)); + Assert.Empty(source().Take(..^4)); + Assert.Empty(source().Take(..6)); + + // All. + Assert.Equal(source()[..], source().Take(..)); + + // Single element in the middle. + Assert.Empty(source().Take(^9..2)); + Assert.Empty(source().Take(2..3)); + Assert.Empty(source().Take(2..^7)); + Assert.Empty(source().Take(^5..^4)); + + // Single element at start. + Assert.Empty(source().Take(^10..1)); + Assert.Empty(source().Take(0..1)); + Assert.Empty(source().Take(0..^9)); + Assert.Empty(source().Take(^10..^9)); + + // Single element at end. + Assert.Empty(source().Take(^1..^10)); + Assert.Empty(source().Take(9..10)); + Assert.Empty(source().Take(9..^9)); + Assert.Empty(source().Take(^1..^9)); + + // No element. + Assert.Empty(source().Take(3..3)); + Assert.Empty(source().Take(6..^4)); + Assert.Empty(source().Take(3..^7)); + Assert.Empty(source().Take(^3..7)); + Assert.Empty(source().Take(^6..^6)); + + // Invalid range. + Assert.Empty(source().Take(3..2)); + Assert.Empty(source().Take(6..^5)); + Assert.Empty(source().Take(3..^8)); + Assert.Empty(source().Take(^6..^7)); + } + + [Fact] + public void EmptySource_DoNotThrowException_NotList() + { + int[] source = { }; + + // Multiple elements in the middle. + Assert.Empty(ForceNotCollection(source).Take(^9..5)); + Assert.Empty(ForceNotCollection(source).Take(2..7)); + Assert.Empty(ForceNotCollection(source).Take(2..^4)); + Assert.Empty(ForceNotCollection(source).Take(^7..^4)); + + // Range with default index. + Assert.Empty(ForceNotCollection(source).Take(^9..)); + Assert.Empty(ForceNotCollection(source).Take(2..)); + Assert.Empty(ForceNotCollection(source).Take(..^4)); + Assert.Empty(ForceNotCollection(source).Take(..6)); + + // All. + Assert.Equal(source[..], ForceNotCollection(source).Take(..)); + + // Single element in the middle. + Assert.Empty(ForceNotCollection(source).Take(^9..2)); + Assert.Empty(ForceNotCollection(source).Take(2..3)); + Assert.Empty(ForceNotCollection(source).Take(2..^7)); + Assert.Empty(ForceNotCollection(source).Take(^5..^4)); + + // Single element at start. + Assert.Empty(ForceNotCollection(source).Take(^10..1)); + Assert.Empty(ForceNotCollection(source).Take(0..1)); + Assert.Empty(ForceNotCollection(source).Take(0..^9)); + Assert.Empty(ForceNotCollection(source).Take(^10..^9)); + + // Single element at end. + Assert.Empty(ForceNotCollection(source).Take(^1..^10)); + Assert.Empty(ForceNotCollection(source).Take(9..10)); + Assert.Empty(ForceNotCollection(source).Take(9..^9)); + Assert.Empty(ForceNotCollection(source).Take(^1..^9)); + + // No element. + Assert.Empty(ForceNotCollection(source).Take(3..3)); + Assert.Empty(ForceNotCollection(source).Take(6..^4)); + Assert.Empty(ForceNotCollection(source).Take(3..^7)); + Assert.Empty(ForceNotCollection(source).Take(^3..7)); + Assert.Empty(ForceNotCollection(source).Take(^6..^6)); + + // Invalid range. + Assert.Empty(ForceNotCollection(source).Take(3..2)); + Assert.Empty(ForceNotCollection(source).Take(6..^5)); + Assert.Empty(ForceNotCollection(source).Take(3..^8)); + Assert.Empty(ForceNotCollection(source).Take(^6..^7)); + } + + [Fact] + public void EmptySource_DoNotThrowException_ListPartition() + { + int[] source = { }; + + // Multiple elements in the middle. + Assert.Empty(ListPartitionOrEmpty(source).Take(^9..5)); + Assert.Empty(ListPartitionOrEmpty(source).Take(2..7)); + Assert.Empty(ListPartitionOrEmpty(source).Take(2..^4)); + Assert.Empty(ListPartitionOrEmpty(source).Take(^7..^4)); + + // Range with default index. + Assert.Empty(ListPartitionOrEmpty(source).Take(^9..)); + Assert.Empty(ListPartitionOrEmpty(source).Take(2..)); + Assert.Empty(ListPartitionOrEmpty(source).Take(..^4)); + Assert.Empty(ListPartitionOrEmpty(source).Take(..6)); + + // All. + Assert.Equal(source[..], ListPartitionOrEmpty(source).Take(..)); + + // Single element in the middle. + Assert.Empty(ListPartitionOrEmpty(source).Take(^9..2)); + Assert.Empty(ListPartitionOrEmpty(source).Take(2..3)); + Assert.Empty(ListPartitionOrEmpty(source).Take(2..^7)); + Assert.Empty(ListPartitionOrEmpty(source).Take(^5..^4)); + + // Single element at start. + Assert.Empty(ListPartitionOrEmpty(source).Take(^10..1)); + Assert.Empty(ListPartitionOrEmpty(source).Take(0..1)); + Assert.Empty(ListPartitionOrEmpty(source).Take(0..^9)); + Assert.Empty(ListPartitionOrEmpty(source).Take(^10..^9)); + + // Single element at end. + Assert.Empty(ListPartitionOrEmpty(source).Take(^1..^10)); + Assert.Empty(ListPartitionOrEmpty(source).Take(9..10)); + Assert.Empty(ListPartitionOrEmpty(source).Take(9..^9)); + Assert.Empty(ListPartitionOrEmpty(source).Take(^1..^9)); + + // No element. + Assert.Empty(ListPartitionOrEmpty(source).Take(3..3)); + Assert.Empty(ListPartitionOrEmpty(source).Take(6..^4)); + Assert.Empty(ListPartitionOrEmpty(source).Take(3..^7)); + Assert.Empty(ListPartitionOrEmpty(source).Take(^3..7)); + Assert.Empty(ListPartitionOrEmpty(source).Take(^6..^6)); + + // Invalid range. + Assert.Empty(ListPartitionOrEmpty(source).Take(3..2)); + Assert.Empty(ListPartitionOrEmpty(source).Take(6..^5)); + Assert.Empty(ListPartitionOrEmpty(source).Take(3..^8)); + Assert.Empty(ListPartitionOrEmpty(source).Take(^6..^7)); + } + + [Fact] + public void EmptySource_DoNotThrowException_EnumerablePartition() + { + int[] source = { }; + + // Multiple elements in the middle. + Assert.Empty(EnumerablePartitionOrEmpty(source).Take(^9..5)); + Assert.Empty(EnumerablePartitionOrEmpty(source).Take(2..7)); + Assert.Empty(EnumerablePartitionOrEmpty(source).Take(2..^4)); + Assert.Empty(EnumerablePartitionOrEmpty(source).Take(^7..^4)); + + // Range with default index. + Assert.Empty(EnumerablePartitionOrEmpty(source).Take(^9..)); + Assert.Empty(EnumerablePartitionOrEmpty(source).Take(2..)); + Assert.Empty(EnumerablePartitionOrEmpty(source).Take(..^4)); + Assert.Empty(EnumerablePartitionOrEmpty(source).Take(..6)); + + // All. + Assert.Equal(source[..], EnumerablePartitionOrEmpty(source).Take(..)); + + // Single element in the middle. + Assert.Empty(EnumerablePartitionOrEmpty(source).Take(^9..2)); + Assert.Empty(EnumerablePartitionOrEmpty(source).Take(2..3)); + Assert.Empty(EnumerablePartitionOrEmpty(source).Take(2..^7)); + Assert.Empty(EnumerablePartitionOrEmpty(source).Take(^5..^4)); + + // Single element at start. + Assert.Empty(EnumerablePartitionOrEmpty(source).Take(^10..1)); + Assert.Empty(EnumerablePartitionOrEmpty(source).Take(0..1)); + Assert.Empty(EnumerablePartitionOrEmpty(source).Take(0..^9)); + Assert.Empty(EnumerablePartitionOrEmpty(source).Take(^10..^9)); + + // Single element at end. + Assert.Empty(EnumerablePartitionOrEmpty(source).Take(^1..^10)); + Assert.Empty(EnumerablePartitionOrEmpty(source).Take(9..10)); + Assert.Empty(EnumerablePartitionOrEmpty(source).Take(9..^9)); + Assert.Empty(EnumerablePartitionOrEmpty(source).Take(^1..^9)); + + // No element. + Assert.Empty(EnumerablePartitionOrEmpty(source).Take(3..3)); + Assert.Empty(EnumerablePartitionOrEmpty(source).Take(6..^4)); + Assert.Empty(EnumerablePartitionOrEmpty(source).Take(3..^7)); + Assert.Empty(EnumerablePartitionOrEmpty(source).Take(^3..7)); + Assert.Empty(EnumerablePartitionOrEmpty(source).Take(^6..^6)); + + // Invalid range. + Assert.Empty(EnumerablePartitionOrEmpty(source).Take(3..2)); + Assert.Empty(EnumerablePartitionOrEmpty(source).Take(6..^5)); + Assert.Empty(EnumerablePartitionOrEmpty(source).Take(3..^8)); + Assert.Empty(EnumerablePartitionOrEmpty(source).Take(^6..^7)); } } }