From 4f846fedc602682add0f62aa8695cb73a86d76e7 Mon Sep 17 00:00:00 2001 From: Dixin Date: Tue, 26 Jan 2021 23:46:20 -0800 Subject: [PATCH 01/35] Implement dotnet/runtime#28776: Implement LINQ APIs for index and range. --- .../ref/System.Linq.Queryable.cs | 3 + .../src/ILLink/ILLink.Suppressions.xml | 24 ++- .../src/System/Linq/CachedReflection.cs | 46 +++-- .../src/System/Linq/Queryable.cs | 48 ++++- src/libraries/System.Linq/ref/System.Linq.cs | 3 + .../System.Linq/src/System/Linq/ElementAt.cs | 125 +++++++++++++ .../System.Linq/src/System/Linq/Take.cs | 165 ++++++++++++++++++ 7 files changed, 396 insertions(+), 18 deletions(-) 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 e93d91af3dadcb..93e5f59fafe0af 100644 --- a/src/libraries/System.Linq.Queryable/ref/System.Linq.Queryable.cs +++ b/src/libraries/System.Linq.Queryable/ref/System.Linq.Queryable.cs @@ -75,7 +75,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; } @@ -153,6 +155,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/ILLink/ILLink.Suppressions.xml b/src/libraries/System.Linq.Queryable/src/ILLink/ILLink.Suppressions.xml index 81bfe8dd961229..d2ce6aedef441d 100644 --- a/src/libraries/System.Linq.Queryable/src/ILLink/ILLink.Suppressions.xml +++ b/src/libraries/System.Linq.Queryable/src/ILLink/ILLink.Suppressions.xml @@ -167,13 +167,25 @@ ILLink IL2060 member - M:System.Linq.CachedReflectionInfo.ElementAt_TSource_2(System.Type) + M:System.Linq.CachedReflectionInfo.ElementAt_Int32_TSource_2(System.Type) ILLink IL2060 member - M:System.Linq.CachedReflectionInfo.ElementAtOrDefault_TSource_2(System.Type) + M:System.Linq.CachedReflectionInfo.ElementAt_Index_TSource_2(System.Type) + + + ILLink + IL2060 + member + M:System.Linq.CachedReflectionInfo.ElementAtOrDefault_Int32_TSource_2(System.Type) + + + ILLink + IL2060 + member + M:System.Linq.CachedReflectionInfo.ElementAtOrDefault_Index_TSource_2(System.Type) ILLink @@ -557,7 +569,13 @@ ILLink IL2060 member - M:System.Linq.CachedReflectionInfo.Take_TSource_2(System.Type) + M:System.Linq.CachedReflectionInfo.Take_Int32_TSource_2(System.Type) + + + ILLink + IL2060 + member + M:System.Linq.CachedReflectionInfo.Take_Range_TSource_2(System.Type) ILLink 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 943a72b0b6d488..d0bc19dfdc9f08 100644 --- a/src/libraries/System.Linq.Queryable/src/System/Linq/CachedReflection.cs +++ b/src/libraries/System.Linq.Queryable/src/System/Linq/CachedReflection.cs @@ -1,6 +1,7 @@ // 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 System.Linq.Expressions; using System.Reflection; @@ -251,18 +252,32 @@ public static MethodInfo Distinct_TSource_2(Type TSource) => (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 ?? + (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 ?? + (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 ?? + (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 ?? + (s_ElementAtOrDefault_Index_TSource_2 = new Func, Index, object?>(Queryable.ElementAtOrDefault).GetMethodInfo().GetGenericMethodDefinition())) .MakeGenericMethod(TSource); private static MethodInfo? s_Except_TSource_2; @@ -752,11 +767,18 @@ public static MethodInfo Sum_Decimal_TSource_2(Type TSource) => (s_Sum_Decimal_TSource_2 = new Func, Expression>, decimal>(Queryable.Sum).GetMethodInfo().GetGenericMethodDefinition())) .MakeGenericMethod(TSource); - private static MethodInfo? s_Take_TSource_2; + private static MethodInfo? s_Take_Int32_TSource_2; + + public static MethodInfo Take_Int32_TSource_2(Type TSource) => + (s_Take_Int32_TSource_2 ?? + (s_Take_Int32_TSource_2 = new Func, int, IQueryable>(Queryable.Take).GetMethodInfo().GetGenericMethodDefinition())) + .MakeGenericMethod(TSource); + + 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 ?? + (s_Take_Range_TSource_2 = new Func, Range, IQueryable>(Queryable.Take).GetMethodInfo().GetGenericMethodDefinition())) .MakeGenericMethod(TSource); private static MethodInfo? s_TakeWhile_TSource_2; 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 7827249013cd0e..2efe18e5503576 100644 --- a/src/libraries/System.Linq.Queryable/src/System/Linq/Queryable.cs +++ b/src/libraries/System.Linq.Queryable/src/System/Linq/Queryable.cs @@ -1,6 +1,7 @@ // 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; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; @@ -384,11 +385,24 @@ 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) )); } + [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) { @@ -955,7 +969,22 @@ 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) + )); + } + + [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) )); } @@ -968,7 +997,20 @@ 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) + )); + } + + [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/ref/System.Linq.cs b/src/libraries/System.Linq/ref/System.Linq.cs index 306886754a23d8..b4d5b323382a62 100644 --- a/src/libraries/System.Linq/ref/System.Linq.cs +++ b/src/libraries/System.Linq/ref/System.Linq.cs @@ -51,7 +51,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; } @@ -172,6 +174,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 fa1256a6f22abb..77e8dd331e1efe 100644 --- a/src/libraries/System.Linq/src/System/Linq/ElementAt.cs +++ b/src/libraries/System.Linq/src/System/Linq/ElementAt.cs @@ -1,6 +1,7 @@ // 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 System.Diagnostics.CodeAnalysis; @@ -51,6 +52,68 @@ public static TSource ElementAt(this IEnumerable source, int i return default; } + public static TSource ElementAt(this IEnumerable source, Index index) + { + if (source == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source); + } + + if (!index.IsFromEnd) + { + return source.ElementAt(index.Value); + } + + int indexFromEnd = index.Value; + if (indexFromEnd > 0) + { + if (source is IPartition partition) + { + int count = partition.GetCount(onlyIfCheap: true); + if (count > 0) + { + TSource? element = partition.TryGetElementAt(count - indexFromEnd, out bool found); + if (found) + { + return element!; + } + } + else if (count == 0) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); + } + } + else if (source is IList list) + { + return list[index]; + } + + using IEnumerator e = source.GetEnumerator(); + if (e.MoveNext()) + { + Queue queue = new(); + queue.Enqueue(e.Current); + while (e.MoveNext()) + { + if (queue.Count == indexFromEnd) + { + queue.Dequeue(); + } + + queue.Enqueue(e.Current); + } + + if (queue.Count == indexFromEnd) + { + return queue.Dequeue(); + } + } + } + + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); + return default; + } + public static TSource? ElementAtOrDefault(this IEnumerable source, int index) { if (source == null) @@ -91,5 +154,67 @@ public static TSource ElementAt(this IEnumerable source, int i return default; } + + public static TSource? ElementAtOrDefault(this IEnumerable source, Index index) + { + if (source == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source); + } + + if (!index.IsFromEnd) + { + return source.ElementAtOrDefault(index.Value); + } + + int indexFromEnd = index.Value; + if (indexFromEnd > 0) + { + if (source is IPartition partition) + { + int count = partition.GetCount(onlyIfCheap: true); + if (count > 0) + { + TSource? element = partition.TryGetElementAt(count - indexFromEnd, out bool found); + if (found) + { + return element!; + } + } + else if (count == 0) + { + return default; + } + } + else if (source is IList list) + { + int count = list.Count; + return indexFromEnd <= count ? list[count - indexFromEnd] : default; + } + + using IEnumerator e = source.GetEnumerator(); + if (e.MoveNext()) + { + Queue queue = new(); + queue.Enqueue(e.Current); + while (e.MoveNext()) + { + if (queue.Count == indexFromEnd) + { + queue.Dequeue(); + } + + queue.Enqueue(e.Current); + } + + if (queue.Count == indexFromEnd) + { + return queue.Dequeue(); + } + } + } + + return default; + } } } diff --git a/src/libraries/System.Linq/src/System/Linq/Take.cs b/src/libraries/System.Linq/src/System/Linq/Take.cs index 79ab4e81f00de4..2777dc24b7ca15 100644 --- a/src/libraries/System.Linq/src/System/Linq/Take.cs +++ b/src/libraries/System.Linq/src/System/Linq/Take.cs @@ -20,6 +20,68 @@ public static IEnumerable Take(this IEnumerable sourc TakeIterator(source, count); } + 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 startIndexValue = start.Value; + int endIndexValue = end.Value; + if (source is IPartition partition) + { + if (!isStartIndexFromEnd && !isEndIndexFromEnd) + { + return partition.Skip(startIndexValue).Take(endIndexValue - startIndexValue); + } + + int count = partition.GetCount(onlyIfCheap: true); + if (count == 0) + { + return Empty(); + } + + if (count > 0) + { + if (isStartIndexFromEnd) + { + startIndexValue = count - startIndexValue; + } + + if (isEndIndexFromEnd) + { + endIndexValue = count - endIndexValue; + } + + return partition.Skip(startIndexValue).Take(endIndexValue - startIndexValue); + } + } + else if (source is IList list) + { + int count = list.Count; + + if (count == 0) + { + return Empty(); + } + + Debug.Assert(count > 0); + + int minIndexInclusive = isStartIndexFromEnd ? count - startIndexValue : startIndexValue; + int maxIndexInclusive = (isEndIndexFromEnd ? count - endIndexValue : endIndexValue) - 1; + return minIndexInclusive <= maxIndexInclusive + ? new ListPartition(list, minIndexInclusive, maxIndexInclusive) + : Empty(); + } + + return TakeIterator(source, isStartIndexFromEnd, startIndexValue, isEndIndexFromEnd, endIndexValue); + } + public static IEnumerable TakeWhile(this IEnumerable source, Func predicate) { if (source == null) @@ -94,6 +156,109 @@ public static IEnumerable TakeLast(this IEnumerable s TakeLastIterator(source, count); } + private static IEnumerable TakeIterator(IEnumerable source, bool isStartIndexFromEnd, int startIndexValue, bool isEndIndexFromEnd, int endIndexValue) + { + Debug.Assert(source != null); + + using IEnumerator e = source.GetEnumerator(); + int currentIndex = -1; + if (isStartIndexFromEnd) + { + if (e.MoveNext()) + { + Queue queue = new(); + queue.Enqueue(e.Current); + currentIndex++; + + int takeLastCount = startIndexValue; + while (e.MoveNext()) + { + if (queue.Count == takeLastCount) + { + queue.Dequeue(); + } + + queue.Enqueue(e.Current); + currentIndex++; + } + + if (queue.Count < takeLastCount) + { + yield break; + } + + int minIndexInclusive = currentIndex + 1 - takeLastCount; + int maxIndexInclusive = isEndIndexFromEnd ? currentIndex - endIndexValue : endIndexValue - 1; + for (int index = minIndexInclusive; index <= maxIndexInclusive; index++) + { + yield return queue.Dequeue(); + } + } + } + else + { + int minIndexInclusive = startIndexValue; + if (!e.MoveNext()) + { + yield break; + } + + currentIndex++; + + while (currentIndex < minIndexInclusive && e.MoveNext()) + { + currentIndex++; + } + + if (currentIndex != minIndexInclusive) + { + yield break; + } + + if (isEndIndexFromEnd) + { + int skipLastCount = endIndexValue; + if (skipLastCount > 0) + { + Queue queue = new(); + do + { + if (queue.Count == skipLastCount) + { + yield return queue.Dequeue(); + } + + queue.Enqueue(e.Current); + currentIndex++; + } while (e.MoveNext()); + } + else + { + do + { + yield return e.Current; + currentIndex++; + } while (e.MoveNext()); + } + } + else + { + int maxIndexInclusive = endIndexValue - 1; + if (maxIndexInclusive < minIndexInclusive) + { + yield break; + } + + yield return e.Current; + while (currentIndex < maxIndexInclusive && e.MoveNext()) + { + currentIndex++; + yield return e.Current; + } + } + } + } + private static IEnumerable TakeLastIterator(IEnumerable source, int count) { Debug.Assert(source != null); From 0825e9a0e0b6caf57c7e6fb80d18d525262a7b96 Mon Sep 17 00:00:00 2001 From: Dixin Date: Wed, 27 Jan 2021 00:52:32 -0800 Subject: [PATCH 02/35] Implement dotnet#28776: Implement LINQ APIs for index and range. --- .../System.Linq/src/System/Linq/Take.cs | 120 +++++++++--------- 1 file changed, 61 insertions(+), 59 deletions(-) diff --git a/src/libraries/System.Linq/src/System/Linq/Take.cs b/src/libraries/System.Linq/src/System/Linq/Take.cs index 2777dc24b7ca15..9ec321de5ba264 100644 --- a/src/libraries/System.Linq/src/System/Linq/Take.cs +++ b/src/libraries/System.Linq/src/System/Linq/Take.cs @@ -97,68 +97,11 @@ public static IEnumerable TakeWhile(this IEnumerable return TakeWhileIterator(source, predicate); } - private static IEnumerable TakeWhileIterator(IEnumerable source, Func predicate) - { - foreach (TSource element in source) - { - if (!predicate(element)) - { - break; - } - - yield return element; - } - } - - public static IEnumerable TakeWhile(this IEnumerable source, Func predicate) - { - if (source == null) - { - ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source); - } - - if (predicate == null) - { - ThrowHelper.ThrowArgumentNullException(ExceptionArgument.predicate); - } - - return TakeWhileIterator(source, predicate); - } - - private static IEnumerable TakeWhileIterator(IEnumerable source, Func predicate) - { - int index = -1; - foreach (TSource element in source) - { - checked - { - index++; - } - - if (!predicate(element, index)) - { - break; - } - - yield return element; - } - } - - public static IEnumerable TakeLast(this IEnumerable source, int count) - { - if (source == null) - { - ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source); - } - - return count <= 0 ? - Empty() : - TakeLastIterator(source, count); - } - private static IEnumerable TakeIterator(IEnumerable source, bool isStartIndexFromEnd, int startIndexValue, bool isEndIndexFromEnd, int endIndexValue) { Debug.Assert(source != null); + Debug.Assert(startIndexValue >= 0); + Debug.Assert(endIndexValue >= 0); using IEnumerator e = source.GetEnumerator(); int currentIndex = -1; @@ -259,6 +202,65 @@ private static IEnumerable TakeIterator(IEnumerable s } } + private static IEnumerable TakeWhileIterator(IEnumerable source, Func predicate) + { + foreach (TSource element in source) + { + if (!predicate(element)) + { + break; + } + + yield return element; + } + } + + public static IEnumerable TakeWhile(this IEnumerable source, Func predicate) + { + if (source == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source); + } + + if (predicate == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.predicate); + } + + return TakeWhileIterator(source, predicate); + } + + private static IEnumerable TakeWhileIterator(IEnumerable source, Func predicate) + { + int index = -1; + foreach (TSource element in source) + { + checked + { + index++; + } + + if (!predicate(element, index)) + { + break; + } + + yield return element; + } + } + + public static IEnumerable TakeLast(this IEnumerable source, int count) + { + if (source == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source); + } + + return count <= 0 ? + Empty() : + TakeLastIterator(source, count); + } + private static IEnumerable TakeLastIterator(IEnumerable source, int count) { Debug.Assert(source != null); From ae75de2032f6d50f57add3c564a9413b8a60f006 Mon Sep 17 00:00:00 2001 From: Dixin Date: Wed, 27 Jan 2021 06:35:58 -0800 Subject: [PATCH 03/35] Implement dotnet#28776: LINQ APIs for index and range. --- .../System.Linq/src/System/Linq/Take.cs | 88 +++++++++++-------- 1 file changed, 50 insertions(+), 38 deletions(-) diff --git a/src/libraries/System.Linq/src/System/Linq/Take.cs b/src/libraries/System.Linq/src/System/Linq/Take.cs index 9ec321de5ba264..35cd81f05a2df4 100644 --- a/src/libraries/System.Linq/src/System/Linq/Take.cs +++ b/src/libraries/System.Linq/src/System/Linq/Take.cs @@ -33,6 +33,9 @@ public static IEnumerable Take(this IEnumerable sourc bool isEndIndexFromEnd = end.IsFromEnd; int startIndexValue = start.Value; int endIndexValue = end.Value; + Debug.Assert(startIndexValue >= 0); + Debug.Assert(endIndexValue >= 0); + if (source is IPartition partition) { if (!isStartIndexFromEnd && !isEndIndexFromEnd) @@ -64,7 +67,6 @@ public static IEnumerable Take(this IEnumerable sourc else if (source is IList list) { int count = list.Count; - if (count == 0) { return Empty(); @@ -72,10 +74,18 @@ public static IEnumerable Take(this IEnumerable sourc Debug.Assert(count > 0); - int minIndexInclusive = isStartIndexFromEnd ? count - startIndexValue : startIndexValue; - int maxIndexInclusive = (isEndIndexFromEnd ? count - endIndexValue : endIndexValue) - 1; - return minIndexInclusive <= maxIndexInclusive - ? new ListPartition(list, minIndexInclusive, maxIndexInclusive) + if (isStartIndexFromEnd) + { + startIndexValue = count - startIndexValue; + } + + if (isEndIndexFromEnd) + { + endIndexValue = count - endIndexValue; + } + + return startIndexValue < endIndexValue && startIndexValue < count + ? new ListPartition(list, minIndexInclusive: startIndexValue, maxIndexInclusive: endIndexValue - 1) : Empty(); } @@ -107,40 +117,45 @@ private static IEnumerable TakeIterator(IEnumerable s int currentIndex = -1; if (isStartIndexFromEnd) { - if (e.MoveNext()) + if (!e.MoveNext()) { - Queue queue = new(); - queue.Enqueue(e.Current); - currentIndex++; - - int takeLastCount = startIndexValue; - while (e.MoveNext()) - { - if (queue.Count == takeLastCount) - { - queue.Dequeue(); - } + yield break; + } - queue.Enqueue(e.Current); - currentIndex++; - } + currentIndex++; + Queue queue = new(); + queue.Enqueue(e.Current); - if (queue.Count < takeLastCount) + while (e.MoveNext()) + { + currentIndex++; + if (queue.Count == startIndexValue) { - yield break; + queue.Dequeue(); } - int minIndexInclusive = currentIndex + 1 - takeLastCount; - int maxIndexInclusive = isEndIndexFromEnd ? currentIndex - endIndexValue : endIndexValue - 1; - for (int index = minIndexInclusive; index <= maxIndexInclusive; index++) - { - yield return queue.Dequeue(); - } + queue.Enqueue(e.Current); + } + + if (queue.Count < startIndexValue) + { + yield break; + } + + int count = currentIndex + 1; + startIndexValue = count - startIndexValue; + if (isEndIndexFromEnd) + { + endIndexValue = count - endIndexValue; + } + + for (int index = startIndexValue; index < endIndexValue; index++) + { + yield return queue.Dequeue(); } } else { - int minIndexInclusive = startIndexValue; if (!e.MoveNext()) { yield break; @@ -148,25 +163,24 @@ private static IEnumerable TakeIterator(IEnumerable s currentIndex++; - while (currentIndex < minIndexInclusive && e.MoveNext()) + while (currentIndex < startIndexValue && e.MoveNext()) { currentIndex++; } - if (currentIndex != minIndexInclusive) + if (currentIndex != startIndexValue) { yield break; } if (isEndIndexFromEnd) { - int skipLastCount = endIndexValue; - if (skipLastCount > 0) + if (endIndexValue > 0) { Queue queue = new(); do { - if (queue.Count == skipLastCount) + if (queue.Count == endIndexValue) { yield return queue.Dequeue(); } @@ -186,16 +200,14 @@ private static IEnumerable TakeIterator(IEnumerable s } else { - int maxIndexInclusive = endIndexValue - 1; - if (maxIndexInclusive < minIndexInclusive) + if (startIndexValue >= endIndexValue) { yield break; } yield return e.Current; - while (currentIndex < maxIndexInclusive && e.MoveNext()) + while (++currentIndex < endIndexValue && e.MoveNext()) { - currentIndex++; yield return e.Current; } } From 2fa8291ad12bf5d5f88c2bab217b5fe7c430756d Mon Sep 17 00:00:00 2001 From: Dixin Date: Wed, 27 Jan 2021 06:47:56 -0800 Subject: [PATCH 04/35] Implement dotnet#28776: LINQ APIs for index and range. --- .../System.Linq/src/System/Linq/Take.cs | 36 ++- .../System.Linq/tests/ElementAtTests.cs | 6 + src/libraries/System.Linq/tests/TakeTests.cs | 259 ++++++++++++++++++ 3 files changed, 293 insertions(+), 8 deletions(-) diff --git a/src/libraries/System.Linq/src/System/Linq/Take.cs b/src/libraries/System.Linq/src/System/Linq/Take.cs index 35cd81f05a2df4..49b7317627fb7b 100644 --- a/src/libraries/System.Linq/src/System/Linq/Take.cs +++ b/src/libraries/System.Linq/src/System/Linq/Take.cs @@ -122,13 +122,21 @@ private static IEnumerable TakeIterator(IEnumerable s yield break; } - currentIndex++; + checked + { + currentIndex++; + } + Queue queue = new(); queue.Enqueue(e.Current); while (e.MoveNext()) { - currentIndex++; + checked + { + currentIndex++; + } + if (queue.Count == startIndexValue) { queue.Dequeue(); @@ -142,7 +150,7 @@ private static IEnumerable TakeIterator(IEnumerable s yield break; } - int count = currentIndex + 1; + int count = checked(currentIndex + 1); startIndexValue = count - startIndexValue; if (isEndIndexFromEnd) { @@ -161,11 +169,17 @@ private static IEnumerable TakeIterator(IEnumerable s yield break; } - currentIndex++; + checked + { + currentIndex++; + } while (currentIndex < startIndexValue && e.MoveNext()) { - currentIndex++; + checked + { + currentIndex++; + } } if (currentIndex != startIndexValue) @@ -186,7 +200,10 @@ private static IEnumerable TakeIterator(IEnumerable s } queue.Enqueue(e.Current); - currentIndex++; + checked + { + currentIndex++; + } } while (e.MoveNext()); } else @@ -194,7 +211,10 @@ private static IEnumerable TakeIterator(IEnumerable s do { yield return e.Current; - currentIndex++; + checked + { + currentIndex++; + } } while (e.MoveNext()); } } @@ -206,7 +226,7 @@ private static IEnumerable TakeIterator(IEnumerable s } yield return e.Current; - while (++currentIndex < endIndexValue && e.MoveNext()) + while (checked(++currentIndex) < endIndexValue && e.MoveNext()) { yield return e.Current; } diff --git a/src/libraries/System.Linq/tests/ElementAtTests.cs b/src/libraries/System.Linq/tests/ElementAtTests.cs index 0b78c1ac6fbe93..d233f7efa832e6 100644 --- a/src/libraries/System.Linq/tests/ElementAtTests.cs +++ b/src/libraries/System.Linq/tests/ElementAtTests.cs @@ -79,5 +79,11 @@ public void NullSource_ThrowsArgumentNullException() { AssertExtensions.Throws("source", () => ((IEnumerable)null).ElementAt(2)); } + + [Fact] + public void Index() + { + AssertExtensions.Throws("source", () => ((IEnumerable)null).ElementAt(2)); + } } } diff --git a/src/libraries/System.Linq/tests/TakeTests.cs b/src/libraries/System.Linq/tests/TakeTests.cs index a9580fb22d3c34..c9ed9d4742a056 100644 --- a/src/libraries/System.Linq/tests/TakeTests.cs +++ b/src/libraries/System.Linq/tests/TakeTests.cs @@ -563,5 +563,264 @@ public void DisposeSource(int sourceCount, int count) int expected = count <= 0 ? 0 : -1; Assert.Equal(expected, state); } + + + [Fact] + public void NonEmptySourceTests() + { + int[] source = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + + // Multiple elements in the middle. + Assert.True(source.Take(^9..5).ToArray().SequenceEqual(source[^9..5])); + Assert.True(source.Take(2..7).ToArray().SequenceEqual(source[2..7])); + Assert.True(source.Take(2..^4).ToArray().SequenceEqual(source[2..^4])); + Assert.True(source.Take(^7..^4).ToArray().SequenceEqual(source[^7..^4])); + + Assert.True(source.Hide().Take(^9..5).ToArray().SequenceEqual(source[^9..5])); + Assert.True(source.Hide().Take(2..7).ToArray().SequenceEqual(source[2..7])); + Assert.True(source.Hide().Take(2..^4).ToArray().SequenceEqual(source[2..^4])); + Assert.True(source.Hide().Take(^7..^4).ToArray().SequenceEqual(source[^7..^4])); + + // Rang with one index. + Assert.True(source.Take(^9..).ToArray().SequenceEqual(source[^9..])); + Assert.True(source.Take(2..).ToArray().SequenceEqual(source[2..])); + Assert.True(source.Take(..^4).ToArray().SequenceEqual(source[..^4])); + Assert.True(source.Take(..6).ToArray().SequenceEqual(source[..6])); + + Assert.True(source.Hide().Take(^9..).ToArray().SequenceEqual(source[^9..])); + Assert.True(source.Hide().Take(2..).ToArray().SequenceEqual(source[2..])); + Assert.True(source.Hide().Take(..^4).ToArray().SequenceEqual(source[..^4])); + Assert.True(source.Hide().Take(..6).ToArray().SequenceEqual(source[..6])); + + // All. + Assert.True(source.Take(..).ToArray().SequenceEqual(source[..])); + + Assert.True(source.Hide().Take(..).ToArray().SequenceEqual(source[..])); + + // Single element in the middle. + Assert.True(source.Take(^9..2).ToArray().SequenceEqual(source[^9..2])); + Assert.True(source.Take(2..3).ToArray().SequenceEqual(source[2..3])); + Assert.True(source.Take(2..^7).ToArray().SequenceEqual(source[2..^7])); + Assert.True(source.Take(^5..^4).ToArray().SequenceEqual(source[^5..^4])); + + Assert.True(source.Hide().Take(^9..2).ToArray().SequenceEqual(source[^9..2])); + Assert.True(source.Hide().Take(2..3).ToArray().SequenceEqual(source[2..3])); + Assert.True(source.Hide().Take(2..^7).ToArray().SequenceEqual(source[2..^7])); + Assert.True(source.Hide().Take(^5..^4).ToArray().SequenceEqual(source[^5..^4])); + + // Single element at start. + Assert.True(source.Take(^10..1).ToArray().SequenceEqual(source[^10..1])); + Assert.True(source.Take(0..1).ToArray().SequenceEqual(source[0..1])); + Assert.True(source.Take(0..^9).ToArray().SequenceEqual(source[0..^9])); + Assert.True(source.Take(^10..^9).ToArray().SequenceEqual(source[^10..^9])); + + Assert.True(source.Hide().Take(^10..1).ToArray().SequenceEqual(source[^10..1])); + Assert.True(source.Hide().Take(0..1).ToArray().SequenceEqual(source[0..1])); + Assert.True(source.Hide().Take(0..^9).ToArray().SequenceEqual(source[0..^9])); + Assert.True(source.Hide().Take(^10..^9).ToArray().SequenceEqual(source[^10..^9])); + + // Single element at end. + Assert.True(source.Take(^1..10).ToArray().SequenceEqual(source[^1..10])); + Assert.True(source.Take(9..10).ToArray().SequenceEqual(source[9..10])); + Assert.True(source.Take(9..^0).ToArray().SequenceEqual(source[9..^0])); + Assert.True(source.Take(^1..^0).ToArray().SequenceEqual(source[^1..^0])); + + Assert.True(source.Hide().Take(^1..10).ToArray().SequenceEqual(source[^1..10])); + Assert.True(source.Hide().Take(9..10).ToArray().SequenceEqual(source[9..10])); + Assert.True(source.Hide().Take(9..^0).ToArray().SequenceEqual(source[9..^0])); + Assert.True(source.Hide().Take(^1..^0).ToArray().SequenceEqual(source[^1..^0])); + + // No element. + Assert.True(source.Take(3..3).ToArray().SequenceEqual(source[3..3])); + Assert.True(source.Take(6..^4).ToArray().SequenceEqual(source[6..^4])); + Assert.True(source.Take(3..^7).ToArray().SequenceEqual(source[3..^7])); + Assert.True(source.Take(^3..7).ToArray().SequenceEqual(source[^3..7])); + Assert.True(source.Take(^6..^6).ToArray().SequenceEqual(source[^6..^6])); + + Assert.True(source.Hide().Take(3..3).ToArray().SequenceEqual(source[3..3])); + Assert.True(source.Hide().Take(6..^4).ToArray().SequenceEqual(source[6..^4])); + Assert.True(source.Hide().Take(3..^7).ToArray().SequenceEqual(source[3..^7])); + Assert.True(source.Hide().Take(^3..7).ToArray().SequenceEqual(source[^3..7])); + Assert.True(source.Hide().Take(^6..^6).ToArray().SequenceEqual(source[^6..^6])); + + // Invalid range. + AssertExtensions.Throws(() => source[3..2].ToArray()); + Assert.False(source.Take(3..2).Any()); + AssertExtensions.Throws(() => source[6..^5].ToArray()); + Assert.False(source.Take(6..^5).Any()); + AssertExtensions.Throws(() => source[3..^8].ToArray()); + Assert.False(source.Take(3..^8).Any()); + AssertExtensions.Throws(() => source[^6..^7].ToArray()); + Assert.False(source.Take(^6..^7).Any()); + + AssertExtensions.Throws(() => source[3..2].ToArray()); + Assert.False(source.Hide().Take(3..2).Any()); + AssertExtensions.Throws(() => source[6..^5].ToArray()); + Assert.False(source.Hide().Take(6..^5).Any()); + AssertExtensions.Throws(() => source[3..^8].ToArray()); + Assert.False(source.Hide().Take(3..^8).Any()); + AssertExtensions.Throws(() => source[^6..^7].ToArray()); + Assert.False(source.Hide().Take(^6..^7).Any()); + } + + [Fact] + public void EmptySourceTests() + { + int[] source = { }; + + // Multiple elements in the middle. + AssertExtensions.Throws(() => source[^9..5].ToArray()); + Assert.False(source.Take(^9..5).Any()); + AssertExtensions.Throws(() => source[2..7].ToArray()); + Assert.False(source.Take(2..7).Any()); + AssertExtensions.Throws(() => source[2..^4].ToArray()); + Assert.False(source.Take(2..^4).Any()); + AssertExtensions.Throws(() => source[^7..^4].ToArray()); + Assert.False(source.Take(^7..^4).Any()); + + AssertExtensions.Throws(() => source[^9..5].ToArray()); + Assert.False(source.Hide().Take(^9..5).Any()); + AssertExtensions.Throws(() => source[2..7].ToArray()); + Assert.False(source.Hide().Take(2..7).Any()); + AssertExtensions.Throws(() => source[2..^4].ToArray()); + Assert.False(source.Hide().Take(2..^4).Any()); + AssertExtensions.Throws(() => source[^7..^4].ToArray()); + Assert.False(source.Hide().Take(^7..^4).Any()); + + // Rang with one index. + AssertExtensions.Throws(() => source[^9..].ToArray()); + Assert.False(source.Take(^9..).Any()); + AssertExtensions.Throws(() => source[2..].ToArray()); + Assert.False(source.Take(2..).Any()); + AssertExtensions.Throws(() => source[..^4].ToArray()); + Assert.False(source.Take(..^4).Any()); + AssertExtensions.Throws(() => source[..6].ToArray()); + Assert.False(source.Take(..6).Any()); + + AssertExtensions.Throws(() => source[^9..].ToArray()); + Assert.False(source.Hide().Take(^9..).Any()); + AssertExtensions.Throws(() => source[2..].ToArray()); + Assert.False(source.Hide().Take(2..).Any()); + AssertExtensions.Throws(() => source[..^4].ToArray()); + Assert.False(source.Hide().Take(..^4).Any()); + AssertExtensions.Throws(() => source[..6].ToArray()); + Assert.False(source.Hide().Take(..6).Any()); + + // All. + var xx = source[..]; + Assert.True(source.Take(..).ToArray().SequenceEqual(source[..])); + + Assert.True(source.Hide().Take(..).ToArray().SequenceEqual(source[..])); + + // Single element in the middle. + AssertExtensions.Throws(() => source[^9..2].ToArray()); + Assert.False(source.Take(^9..2).Any()); + AssertExtensions.Throws(() => source[2..3].ToArray()); + Assert.False(source.Take(2..3).Any()); + AssertExtensions.Throws(() => source[2..^7].ToArray()); + Assert.False(source.Take(2..^7).Any()); + AssertExtensions.Throws(() => source[^5..^4].ToArray()); + Assert.False(source.Take(^5..^4).Any()); + + AssertExtensions.Throws(() => source[^9..2].ToArray()); + Assert.False(source.Hide().Take(^9..2).Any()); + AssertExtensions.Throws(() => source[2..3].ToArray()); + Assert.False(source.Hide().Take(2..3).Any()); + AssertExtensions.Throws(() => source[2..^7].ToArray()); + Assert.False(source.Hide().Take(2..^7).Any()); + AssertExtensions.Throws(() => source[^5..^4].ToArray()); + Assert.False(source.Hide().Take(^5..^4).Any()); + + // Single element at start. + AssertExtensions.Throws(() => source[^10..1].ToArray()); + Assert.False(source.Take(^10..1).Any()); + AssertExtensions.Throws(() => source[0..1].ToArray()); + Assert.False(source.Take(0..1).Any()); + AssertExtensions.Throws(() => source[0..^9].ToArray()); + Assert.False(source.Take(0..^9).Any()); + AssertExtensions.Throws(() => source[^10..^9].ToArray()); + Assert.False(source.Take(^10..^9).Any()); + + AssertExtensions.Throws(() => source[^10..1].ToArray()); + Assert.False(source.Hide().Take(^10..1).Any()); + AssertExtensions.Throws(() => source[0..1].ToArray()); + Assert.False(source.Hide().Take(0..1).Any()); + AssertExtensions.Throws(() => source[0..^9].ToArray()); + Assert.False(source.Hide().Take(0..^9).Any()); + AssertExtensions.Throws(() => source[^10..^9].ToArray()); + Assert.False(source.Hide().Take(^10..^9).Any()); + + // Single element at end. + AssertExtensions.Throws(() => source[^1..10].ToArray()); + Assert.False(source.Take(^1..^10).Any()); + AssertExtensions.Throws(() => source[9..10].ToArray()); + Assert.False(source.Take(9..10).Any()); + AssertExtensions.Throws(() => source[9..^0].ToArray()); + Assert.False(source.Take(9..^9).Any()); + AssertExtensions.Throws(() => source[^1..^0].ToArray()); + Assert.False(source.Take(^1..^9).Any()); + + AssertExtensions.Throws(() => source[^1..10].ToArray()); + Assert.False(source.Hide().Take(^1..^10).Any()); + AssertExtensions.Throws(() => source[9..10].ToArray()); + Assert.False(source.Hide().Take(9..10).Any()); + AssertExtensions.Throws(() => source[9..^0].ToArray()); + Assert.False(source.Hide().Take(9..^9).Any()); + AssertExtensions.Throws(() => source[^1..^0].ToArray()); + Assert.False(source.Hide().Take(^1..^9).Any()); + + // No element. + AssertExtensions.Throws(() => source[3..3].ToArray()); + Assert.False(source.Take(3..3).Any()); + AssertExtensions.Throws(() => source[6..^4].ToArray()); + Assert.False(source.Take(6..^4).Any()); + AssertExtensions.Throws(() => source[3..^7].ToArray()); + Assert.False(source.Take(3..^7).Any()); + AssertExtensions.Throws(() => source[^3..7].ToArray()); + Assert.False(source.Take(^3..7).Any()); + AssertExtensions.Throws(() => source[^6..^6].ToArray()); + Assert.False(source.Take(^6..^6).Any()); + + AssertExtensions.Throws(() => source[3..3].ToArray()); + Assert.False(source.Hide().Take(3..3).Any()); + AssertExtensions.Throws(() => source[6..^4].ToArray()); + Assert.False(source.Hide().Take(6..^4).Any()); + AssertExtensions.Throws(() => source[3..^7].ToArray()); + Assert.False(source.Hide().Take(3..^7).Any()); + AssertExtensions.Throws(() => source[^3..7].ToArray()); + Assert.False(source.Hide().Take(^3..7).Any()); + AssertExtensions.Throws(() => source[^6..^6].ToArray()); + Assert.False(source.Hide().Take(^6..^6).Any()); + + // Invalid range. + AssertExtensions.Throws(() => source[3..2].ToArray()); + Assert.False(source.Take(3..2).Any()); + AssertExtensions.Throws(() => source[6..^5].ToArray()); + Assert.False(source.Take(6..^5).Any()); + AssertExtensions.Throws(() => source[3..^8].ToArray()); + Assert.False(source.Take(3..^8).Any()); + AssertExtensions.Throws(() => source[^6..^7].ToArray()); + Assert.False(source.Take(^6..^7).Any()); + + AssertExtensions.Throws(() => source[3..2].ToArray()); + Assert.False(source.Hide().Take(3..2).Any()); + AssertExtensions.Throws(() => source[6..^5].ToArray()); + Assert.False(source.Hide().Take(6..^5).Any()); + AssertExtensions.Throws(() => source[3..^8].ToArray()); + Assert.False(source.Hide().Take(3..^8).Any()); + AssertExtensions.Throws(() => source[^6..^7].ToArray()); + Assert.False(source.Hide().Take(^6..^7).Any()); + } + } + + public static class X + { + public static IEnumerable Hide(this IEnumerable source) + { + foreach (T value in source) + { + yield return value; + } + } } } From 58ba22c54848c6cbe2d7d2ae4ed34ffa0eccabd4 Mon Sep 17 00:00:00 2001 From: Dixin Date: Wed, 27 Jan 2021 08:08:03 -0800 Subject: [PATCH 05/35] Implement dotnet#28776: LINQ APIs for index and range. --- .../System.Linq/src/System/Linq/Take.cs | 57 +++---------------- 1 file changed, 8 insertions(+), 49 deletions(-) diff --git a/src/libraries/System.Linq/src/System/Linq/Take.cs b/src/libraries/System.Linq/src/System/Linq/Take.cs index 49b7317627fb7b..47bd1ce10e8c73 100644 --- a/src/libraries/System.Linq/src/System/Linq/Take.cs +++ b/src/libraries/System.Linq/src/System/Linq/Take.cs @@ -36,57 +36,16 @@ public static IEnumerable Take(this IEnumerable sourc Debug.Assert(startIndexValue >= 0); Debug.Assert(endIndexValue >= 0); - if (source is IPartition partition) + if (!isStartIndexFromEnd && !isEndIndexFromEnd) { - if (!isStartIndexFromEnd && !isEndIndexFromEnd) - { - return partition.Skip(startIndexValue).Take(endIndexValue - startIndexValue); - } - - int count = partition.GetCount(onlyIfCheap: true); - if (count == 0) - { - return Empty(); - } - - if (count > 0) - { - if (isStartIndexFromEnd) + return startIndexValue >= endIndexValue + ? Empty() + : source switch { - startIndexValue = count - startIndexValue; - } - - if (isEndIndexFromEnd) - { - endIndexValue = count - endIndexValue; - } - - return partition.Skip(startIndexValue).Take(endIndexValue - startIndexValue); - } - } - else if (source is IList list) - { - int count = list.Count; - if (count == 0) - { - return Empty(); - } - - Debug.Assert(count > 0); - - if (isStartIndexFromEnd) - { - startIndexValue = count - startIndexValue; - } - - if (isEndIndexFromEnd) - { - endIndexValue = count - endIndexValue; - } - - return startIndexValue < endIndexValue && startIndexValue < count - ? new ListPartition(list, minIndexInclusive: startIndexValue, maxIndexInclusive: endIndexValue - 1) - : Empty(); + IPartition partition => partition.Skip(startIndexValue).Take(endIndexValue - startIndexValue), + IList list => new ListPartition(list, startIndexValue, endIndexValue - 1), + _ => new EnumerablePartition(source, startIndexValue, endIndexValue - 1) + }; } return TakeIterator(source, isStartIndexFromEnd, startIndexValue, isEndIndexFromEnd, endIndexValue); From 4a0698cc3774d3703471aadb5f48b24c6366385e Mon Sep 17 00:00:00 2001 From: Dixin Date: Mon, 1 Feb 2021 21:57:52 -0800 Subject: [PATCH 06/35] Implement dotnet#28776: LINQ APIs for index and range. --- .../System.Linq/src/System/Linq/Take.cs | 94 +++++++++---------- 1 file changed, 46 insertions(+), 48 deletions(-) diff --git a/src/libraries/System.Linq/src/System/Linq/Take.cs b/src/libraries/System.Linq/src/System/Linq/Take.cs index 47bd1ce10e8c73..0812005d05fe28 100644 --- a/src/libraries/System.Linq/src/System/Linq/Take.cs +++ b/src/libraries/System.Linq/src/System/Linq/Take.cs @@ -31,46 +31,30 @@ public static IEnumerable Take(this IEnumerable sourc Index end = range.End; bool isStartIndexFromEnd = start.IsFromEnd; bool isEndIndexFromEnd = end.IsFromEnd; - int startIndexValue = start.Value; - int endIndexValue = end.Value; - Debug.Assert(startIndexValue >= 0); - Debug.Assert(endIndexValue >= 0); + int startIndex = start.Value; + int endIndex = end.Value; if (!isStartIndexFromEnd && !isEndIndexFromEnd) { - return startIndexValue >= endIndexValue + return startIndex >= endIndex ? Empty() : source switch { - IPartition partition => partition.Skip(startIndexValue).Take(endIndexValue - startIndexValue), - IList list => new ListPartition(list, startIndexValue, endIndexValue - 1), - _ => new EnumerablePartition(source, startIndexValue, endIndexValue - 1) + IPartition partition => partition.Skip(startIndex).Take(endIndex - startIndex), + IList list => new ListPartition(list, startIndex, endIndex - 1), + _ => new EnumerablePartition(source, startIndex, endIndex - 1) }; } - return TakeIterator(source, isStartIndexFromEnd, startIndexValue, isEndIndexFromEnd, endIndexValue); + return TakeIterator(source, isStartIndexFromEnd, startIndex, isEndIndexFromEnd, endIndex); } - public static IEnumerable TakeWhile(this IEnumerable source, Func predicate) - { - if (source == null) - { - ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source); - } - - if (predicate == null) - { - ThrowHelper.ThrowArgumentNullException(ExceptionArgument.predicate); - } - - return TakeWhileIterator(source, predicate); - } - - private static IEnumerable TakeIterator(IEnumerable source, bool isStartIndexFromEnd, int startIndexValue, bool isEndIndexFromEnd, int endIndexValue) + private static IEnumerable TakeIterator( + IEnumerable source, bool isStartIndexFromEnd, int startIndex, bool isEndIndexFromEnd, int endIndex) { Debug.Assert(source != null); - Debug.Assert(startIndexValue >= 0); - Debug.Assert(endIndexValue >= 0); + Debug.Assert(startIndex >= 0); + Debug.Assert(endIndex >= 0); using IEnumerator e = source.GetEnumerator(); int currentIndex = -1; @@ -96,7 +80,7 @@ private static IEnumerable TakeIterator(IEnumerable s currentIndex++; } - if (queue.Count == startIndexValue) + if (queue.Count == startIndex) { queue.Dequeue(); } @@ -104,19 +88,26 @@ private static IEnumerable TakeIterator(IEnumerable s queue.Enqueue(e.Current); } - if (queue.Count < startIndexValue) + int count = checked(currentIndex + 1); + Debug.Assert(queue.Count == Math.Min(count, startIndex)); + + startIndex = count - startIndex; + if (startIndex < 0) { - yield break; + startIndex = 0; } - int count = checked(currentIndex + 1); - startIndexValue = count - startIndexValue; if (isEndIndexFromEnd) { - endIndexValue = count - endIndexValue; + endIndex = count - endIndex; + } + else if (endIndex > count) + { + endIndex = count; } - for (int index = startIndexValue; index < endIndexValue; index++) + Debug.Assert(endIndex - startIndex <= queue.Count); + for (int index = startIndex; index < endIndex; index++) { yield return queue.Dequeue(); } @@ -133,7 +124,7 @@ private static IEnumerable TakeIterator(IEnumerable s currentIndex++; } - while (currentIndex < startIndexValue && e.MoveNext()) + while (currentIndex < startIndex && e.MoveNext()) { checked { @@ -141,28 +132,24 @@ private static IEnumerable TakeIterator(IEnumerable s } } - if (currentIndex != startIndexValue) + if (currentIndex != startIndex) { yield break; } if (isEndIndexFromEnd) { - if (endIndexValue > 0) + if (endIndex > 0) { Queue queue = new(); do { - if (queue.Count == endIndexValue) + if (queue.Count == endIndex) { yield return queue.Dequeue(); } queue.Enqueue(e.Current); - checked - { - currentIndex++; - } } while (e.MoveNext()); } else @@ -170,22 +157,18 @@ private static IEnumerable TakeIterator(IEnumerable s do { yield return e.Current; - checked - { - currentIndex++; - } } while (e.MoveNext()); } } else { - if (startIndexValue >= endIndexValue) + if (startIndex >= endIndex) { yield break; } yield return e.Current; - while (checked(++currentIndex) < endIndexValue && e.MoveNext()) + while (checked(++currentIndex) < endIndex && e.MoveNext()) { yield return e.Current; } @@ -193,6 +176,21 @@ private static IEnumerable TakeIterator(IEnumerable s } } + public static IEnumerable TakeWhile(this IEnumerable source, Func predicate) + { + if (source == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source); + } + + if (predicate == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.predicate); + } + + return TakeWhileIterator(source, predicate); + } + private static IEnumerable TakeWhileIterator(IEnumerable source, Func predicate) { foreach (TSource element in source) From 6317a99af71731f6da1708f1f19664240fcb549f Mon Sep 17 00:00:00 2001 From: Dixin Date: Tue, 2 Feb 2021 14:34:43 -0800 Subject: [PATCH 07/35] Implement dotnet/runtime#28776: LINQ APIs for index and range. --- src/libraries/System.Linq/tests/TakeTests.cs | 516 +++++++++++++++++-- 1 file changed, 474 insertions(+), 42 deletions(-) diff --git a/src/libraries/System.Linq/tests/TakeTests.cs b/src/libraries/System.Linq/tests/TakeTests.cs index c9ed9d4742a056..a4a472f544ab51 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; @@ -15,44 +14,85 @@ private static IEnumerable GuaranteeNotIList(IEnumerable source) yield return element; } + private static T[] Repeat(Func factory, int count = 5) + { + T[] results = new T[count]; + for (int i = 0; i < results.Length; i++) + { + results[i] = factory(); + } + + return results; + } + [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.Take(9), q.Take(9)); + var q = Repeat(() => from x in new[] { 9999, 0, 888, -1, 66, -777, 1, 2, -12345 } + where x > int.MinValue + select x); + + Assert.Equal(q[0].Take(9), q[0].Take(9)); + + Assert.Equal(q[1].Take(0..9), q[1].Take(0..9)); + Assert.Equal(q[2].Take(^9..9), q[2].Take(^9..9)); + Assert.Equal(q[3].Take(0..^0), q[3].Take(0..^0)); + Assert.Equal(q[4].Take(^9..^0), q[4].Take(^9..^0)); + //Assert.Equal(q[5].Take(..9), q[5].Take(..9)); + //Assert.Equal(q[6].Take(..^0), q[6].Take(..^0)); + //Assert.Equal(q[7].Take(0..), q[7].Take(0..)); + //Assert.Equal(q[8].Take(..), q[8].Take(..)); + //Assert.Equal(q[9].Take(^9..), q[9].Take(^9..)); } [Fact] public void SameResultsRepeatCallsIntQueryIList() { - var q = (from x in new[] { 9999, 0, 888, -1, 66, -777, 1, 2, -12345 } + var q = Repeat(() => (from x in new[] { 9999, 0, 888, -1, 66, -777, 1, 2, -12345 } where x > Int32.MinValue - select x).ToList(); - - Assert.Equal(q.Take(9), q.Take(9)); + select x).ToList()); + + Assert.Equal(q[0].Take(9), q[0].Take(9)); + + Assert.Equal(q[1].Take(0..9), q[1].Take(0..9)); + Assert.Equal(q[2].Take(^9..9), q[2].Take(^9..9)); + Assert.Equal(q[3].Take(0..^0), q[3].Take(0..^0)); + Assert.Equal(q[4].Take(^9..^0), q[4].Take(^9..^0)); + //Assert.Equal(q[5].Take(..9), q[5].Take(..9)); + //Assert.Equal(q[6].Take(..^0), q[6].Take(..^0)); + //Assert.Equal(q[7].Take(0..), q[7].Take(0..)); + //Assert.Equal(q[8].Take(..), q[8].Take(..)); + //Assert.Equal(q[9].Take(^9..), q[9].Take(^9..)); } [Fact] public void SameResultsRepeatCallsStringQuery() { - var q = from x in new[] { "!@#$%^", "C", "AAA", "", "Calling Twice", "SoS", string.Empty } + var q = Repeat(() => from x in new[] { "!@#$%^", "C", "AAA", "", "Calling Twice", "SoS", string.Empty } where !string.IsNullOrEmpty(x) - select x; + select x); + + Assert.Equal(q[0].Take(7), q[0].Take(7)); - Assert.Equal(q.Take(7), q.Take(7)); + Assert.Equal(q[1].Take(0..7), q[1].Take(0..7)); + Assert.Equal(q[2].Take(^7..7), q[2].Take(^7..7)); + Assert.Equal(q[3].Take(0..^0), q[3].Take(0..^0)); + Assert.Equal(q[4].Take(^7..^0), q[4].Take(^7..^0)); } [Fact] public void SameResultsRepeatCallsStringQueryIList() { - var q = (from x in new[] { "!@#$%^", "C", "AAA", "", "Calling Twice", "SoS", String.Empty } + var q = Repeat(() => (from x in new[] { "!@#$%^", "C", "AAA", "", "Calling Twice", "SoS", String.Empty } where !String.IsNullOrEmpty(x) - select x).ToList(); + select x).ToList()); + + Assert.Equal(q[0].Take(7), q[0].Take(7)); - Assert.Equal(q.Take(7), q.Take(7)); + Assert.Equal(q[1].Take(0..7), q[1].Take(0..7)); + Assert.Equal(q[2].Take(^7..7), q[2].Take(^7..7)); + Assert.Equal(q[3].Take(0..^0), q[3].Take(0..^0)); + Assert.Equal(q[4].Take(^7..^0), q[4].Take(^7..^0)); } [Fact] @@ -60,6 +100,11 @@ public void SourceEmptyCountPositive() { int[] source = { }; 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,6 +112,11 @@ 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] @@ -74,6 +124,8 @@ public void SourceNonEmptyCountNegative() { int[] source = { 2, 5, 9, 1 }; Assert.Empty(source.Take(-5)); + + Assert.Empty(source.Take(0..^9)); } [Fact] @@ -81,6 +133,8 @@ public void SourceNonEmptyCountNegativeNotIList() { var source = GuaranteeNotIList(new[] { 2, 5, 9, 1 }); Assert.Empty(source.Take(-5)); + + Assert.Empty(source.Take(0..^9)); } [Fact] @@ -88,6 +142,11 @@ public void SourceNonEmptyCountZero() { int[] source = { 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] @@ -95,6 +154,11 @@ public void SourceNonEmptyCountZeroNotIList() { var source = GuaranteeNotIList(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] @@ -104,6 +168,11 @@ public void SourceNonEmptyCountOne() 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] @@ -113,6 +182,11 @@ public void SourceNonEmptyCountOneNotIList() 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] @@ -121,6 +195,11 @@ public void SourceNonEmptyTakeAllExactly() int[] source = { 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] @@ -129,6 +208,11 @@ public void SourceNonEmptyTakeAllExactlyNotIList() var source = GuaranteeNotIList(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] @@ -138,6 +222,11 @@ public void SourceNonEmptyTakeAllButOne() 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] @@ -147,6 +236,11 @@ public void RunOnce() 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] @@ -156,6 +250,11 @@ public void SourceNonEmptyTakeAllButOneNotIList() int[] expected = { 2, 5, 9 }; Assert.Equal(expected, source.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] @@ -164,6 +263,9 @@ public void SourceNonEmptyTakeExcessive() int?[] source = { 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] @@ -172,6 +274,9 @@ public void SourceNonEmptyTakeExcessiveNotIList() var source = GuaranteeNotIList(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] @@ -179,15 +284,25 @@ public void ThrowsOnNullSource() { int[] 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 ForcedToEnumeratorDoesntEnumerate() { - 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 en1 = iterator1 as IEnumerator; + Assert.False(en1 != null && en1.MoveNext()); + + var iterator2 = 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 en2 = iterator2 as IEnumerator; + Assert.False(en2 != null && en2.MoveNext()); } [Fact] @@ -196,15 +311,36 @@ 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(2); + // Don't insist on this behaviour, but check it's correct if it happens + var en2 = iterator2 as IEnumerator; + Assert.False(en2 != null && en2.MoveNext()); } [Fact] @@ -213,6 +349,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 +362,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).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] @@ -229,6 +375,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 +388,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 taken1 = source.Take(3); + Assert.Equal(1, taken1.ElementAt(0)); + Assert.Equal(3, taken1.ElementAt(2)); + AssertExtensions.Throws("index", () => taken1.ElementAt(-1)); + AssertExtensions.Throws("index", () => taken1.ElementAt(3)); + + var taken2 = source.Take(0..3); + Assert.Equal(1, taken2.ElementAt(0)); + Assert.Equal(3, taken2.ElementAt(2)); + AssertExtensions.Throws("index", () => taken2.ElementAt(-1)); + AssertExtensions.Throws("index", () => taken2.ElementAt(3)); + + taken2 = source.Take(^6..3); + Assert.Equal(1, taken2.ElementAt(0)); + Assert.Equal(3, taken2.ElementAt(2)); + AssertExtensions.Throws("index", () => taken2.ElementAt(-1)); + AssertExtensions.Throws("index", () => taken2.ElementAt(3)); + + taken2 = source.Take(0..^3); + Assert.Equal(1, taken2.ElementAt(0)); + Assert.Equal(3, taken2.ElementAt(2)); + AssertExtensions.Throws("index", () => taken2.ElementAt(-1)); + AssertExtensions.Throws("index", () => taken2.ElementAt(3)); + + taken2 = source.Take(^6..^3); + Assert.Equal(1, taken2.ElementAt(0)); + Assert.Equal(3, taken2.ElementAt(2)); + AssertExtensions.Throws("index", () => taken2.ElementAt(-1)); + AssertExtensions.Throws("index", () => taken2.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 taken1 = source.Take(3); + Assert.Equal(1, taken1.ElementAt(0)); + Assert.Equal(3, taken1.ElementAt(2)); + AssertExtensions.Throws("index", () => taken1.ElementAt(-1)); + AssertExtensions.Throws("index", () => taken1.ElementAt(3)); + + var taken2 = source.Take(0..3); + Assert.Equal(1, taken2.ElementAt(0)); + Assert.Equal(3, taken2.ElementAt(2)); + AssertExtensions.Throws("index", () => taken2.ElementAt(-1)); + AssertExtensions.Throws("index", () => taken2.ElementAt(3)); + + taken2 = source.Take(^6..3); + Assert.Equal(1, taken2.ElementAt(0)); + Assert.Equal(3, taken2.ElementAt(2)); + AssertExtensions.Throws("index", () => taken2.ElementAt(-1)); + AssertExtensions.Throws("index", () => taken2.ElementAt(3)); + + taken2 = source.Take(0..^3); + Assert.Equal(1, taken2.ElementAt(0)); + Assert.Equal(3, taken2.ElementAt(2)); + AssertExtensions.Throws("index", () => taken2.ElementAt(-1)); + AssertExtensions.Throws("index", () => taken2.ElementAt(3)); + + taken2 = source.Take(^6..^3); + Assert.Equal(1, taken2.ElementAt(0)); + Assert.Equal(3, taken2.ElementAt(2)); + AssertExtensions.Throws("index", () => taken2.ElementAt(-1)); + AssertExtensions.Throws("index", () => taken2.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 taken1 = source.Take(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(0..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)); + + 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)); + + taken2 = source.Take(0..^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)); + + 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)); } [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 taken1 = source.Take(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(0..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)); + + 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)); + + taken2 = source.Take(0..^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)); + + 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)); } [Fact] @@ -292,6 +544,24 @@ 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(^10..^5).First()); } [Fact] @@ -303,6 +573,24 @@ public void FirstNotIList() 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(^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,6 +602,30 @@ 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] @@ -325,6 +637,30 @@ public void FirstOrDefaultNotIList() 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,6 +672,30 @@ 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] @@ -347,6 +707,30 @@ public void LastNotIList() Assert.Equal(5, source.Take(40).Last()); Assert.Throws(() => source.Take(0).Last()); Assert.Throws(() => GuaranteeNotIList(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(() => GuaranteeNotIList(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(() => GuaranteeNotIList(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(() => GuaranteeNotIList(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(() => GuaranteeNotIList(Array.Empty()).Take(^40..^0).Last()); } [Fact] @@ -358,6 +742,30 @@ 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] @@ -369,6 +777,30 @@ public void LastOrDefaultNotIList() 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(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, GuaranteeNotIList(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, GuaranteeNotIList(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, GuaranteeNotIList(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, GuaranteeNotIList(Array.Empty()).Take(^40..^0).LastOrDefault()); } [Fact] From 62570c94988eadecfbfa6aefb047bd679fcb65bd Mon Sep 17 00:00:00 2001 From: Dixin Date: Wed, 3 Feb 2021 04:44:07 -0800 Subject: [PATCH 08/35] Implement dotnet/runtime#28776: LINQ APIs for index and range. --- .../System.Linq/src/System/Linq/Take.cs | 31 +++---- .../tests/ElementAtOrDefaultTests.cs | 88 ++++++++++++++----- .../System.Linq/tests/ElementAtTests.cs | 84 ++++++++++++++---- 3 files changed, 148 insertions(+), 55 deletions(-) diff --git a/src/libraries/System.Linq/src/System/Linq/Take.cs b/src/libraries/System.Linq/src/System/Linq/Take.cs index 0812005d05fe28..be41f5df55f451 100644 --- a/src/libraries/System.Linq/src/System/Linq/Take.cs +++ b/src/libraries/System.Linq/src/System/Linq/Take.cs @@ -56,20 +56,20 @@ private static IEnumerable TakeIterator( Debug.Assert(startIndex >= 0); Debug.Assert(endIndex >= 0); - using IEnumerator e = source.GetEnumerator(); - int currentIndex = -1; if (isStartIndexFromEnd) { - if (!e.MoveNext()) + if (startIndex == 0) { yield break; } - checked + using IEnumerator e = source.GetEnumerator(); + if (!e.MoveNext()) { - currentIndex++; + yield break; } + int index = 0; Queue queue = new(); queue.Enqueue(e.Current); @@ -77,7 +77,7 @@ private static IEnumerable TakeIterator( { checked { - currentIndex++; + index++; } if (queue.Count == startIndex) @@ -88,7 +88,7 @@ private static IEnumerable TakeIterator( queue.Enqueue(e.Current); } - int count = checked(currentIndex + 1); + int count = checked(index + 1); Debug.Assert(queue.Count == Math.Min(count, startIndex)); startIndex = count - startIndex; @@ -107,32 +107,29 @@ private static IEnumerable TakeIterator( } Debug.Assert(endIndex - startIndex <= queue.Count); - for (int index = startIndex; index < endIndex; index++) + for (int rangeIndex = startIndex; rangeIndex < endIndex; rangeIndex++) { yield return queue.Dequeue(); } } else { + using IEnumerator e = source.GetEnumerator(); if (!e.MoveNext()) { yield break; } - checked - { - currentIndex++; - } - - while (currentIndex < startIndex && e.MoveNext()) + int index = 0; + while (index < startIndex && e.MoveNext()) { checked { - currentIndex++; + index++; } } - if (currentIndex != startIndex) + if (index != startIndex) { yield break; } @@ -168,7 +165,7 @@ private static IEnumerable TakeIterator( } yield return e.Current; - while (checked(++currentIndex) < endIndex && e.MoveNext()) + while (checked(++index) < endIndex && e.MoveNext()) { yield return e.Current; } diff --git a/src/libraries/System.Linq/tests/ElementAtOrDefaultTests.cs b/src/libraries/System.Linq/tests/ElementAtOrDefaultTests.cs index 7d9d66b4384206..421f9685470a4f 100644 --- a/src/libraries/System.Linq/tests/ElementAtOrDefaultTests.cs +++ b/src/libraries/System.Linq/tests/ElementAtOrDefaultTests.cs @@ -11,73 +11,121 @@ public class ElementAtOrDefaultTests : EnumerableTests [Fact] public void SameResultsRepeatCallsIntQuery() { - var q = from x in new[] { 9999, 0, 888, -1, 66, -777, 1, 2, -12345 } + var q1 = from x in new[] { 9999, 0, 888, -1, 66, -777, 1, 2, -12345 } where x > int.MinValue select x; + Assert.Equal(q1.ElementAtOrDefault(3), q1.ElementAtOrDefault(3)); - Assert.Equal(q.ElementAtOrDefault(3), q.ElementAtOrDefault(3)); + var q2 = from x in new[] { 9999, 0, 888, -1, 66, -777, 1, 2, -12345 } + where x > int.MinValue + select x; + Assert.Equal(q2.ElementAtOrDefault(new Index(3)), q2.ElementAtOrDefault(new Index(3))); + + var q3 = from x in new[] { 9999, 0, 888, -1, 66, -777, 1, 2, -12345 } + where x > int.MinValue + select x; + Assert.Equal(q3.ElementAtOrDefault(^6), q3.ElementAtOrDefault(^6)); } [Fact] public void SameResultsRepeatCallsStringQuery() { - var q = from x in new[] { "!@#$%^", "C", "AAA", "", "Calling Twice", "SoS", string.Empty } + var q1 = from x in new[] { "!@#$%^", "C", "AAA", "", "Calling Twice", "SoS", string.Empty } where !string.IsNullOrEmpty(x) select x; + Assert.Equal(q1.ElementAtOrDefault(4), q1.ElementAtOrDefault(4)); + + var q2 = from x in new[] { "!@#$%^", "C", "AAA", "", "Calling Twice", "SoS", string.Empty } + where !string.IsNullOrEmpty(x) + select x; + Assert.Equal(q2.ElementAtOrDefault(new Index(4)), q2.ElementAtOrDefault(new Index(4))); - Assert.Equal(q.ElementAtOrDefault(4), q.ElementAtOrDefault(4)); + var q3 = from x in new[] { "!@#$%^", "C", "AAA", "", "Calling Twice", "SoS", string.Empty } + where !string.IsNullOrEmpty(x) + select x; + Assert.Equal(q3.ElementAtOrDefault(^2), q3.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[] { 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[] { 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(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, 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, 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)); + AssertExtensions.Throws("source", () => ((IEnumerable)null).ElementAtOrDefault(new Index(2))); + AssertExtensions.Throws("source", () => ((IEnumerable)null).ElementAtOrDefault(^2)); } } } diff --git a/src/libraries/System.Linq/tests/ElementAtTests.cs b/src/libraries/System.Linq/tests/ElementAtTests.cs index d233f7efa832e6..56438725438c19 100644 --- a/src/libraries/System.Linq/tests/ElementAtTests.cs +++ b/src/libraries/System.Linq/tests/ElementAtTests.cs @@ -11,58 +11,104 @@ public class ElementAtTests : EnumerableTests [Fact] public void SameResultsRepeatCallsIntQuery() { - var q = from x in new[] { 9999, 0, 888, -1, 66, -777, 1, 2, -12345 } + var q1 = from x in new[] { 9999, 0, 888, -1, 66, -777, 1, 2, -12345 } where x > int.MinValue select x; + Assert.Equal(q1.ElementAt(3), q1.ElementAt(3)); - Assert.Equal(q.ElementAt(3), q.ElementAt(3)); + var q2 = from x in new[] { 9999, 0, 888, -1, 66, -777, 1, 2, -12345 } + where x > int.MinValue + select x; + Assert.Equal(q2.ElementAt(new Index(3)), q2.ElementAt(new Index(3))); + + var q3 = from x in new[] { 9999, 0, 888, -1, 66, -777, 1, 2, -12345 } + where x > int.MinValue + select x; + Assert.Equal(q3.ElementAt(^6), q3.ElementAt(^6)); } [Fact] public void SameResultsRepeatCallsStringQuery() { - var q = from x in new[] { "!@#$%^", "C", "AAA", "", "Calling Twice", "SoS", string.Empty } + var q1 = from x in new[] { "!@#$%^", "C", "AAA", "", "Calling Twice", "SoS", string.Empty } where !string.IsNullOrEmpty(x) select x; + Assert.Equal(q1.ElementAt(4), q1.ElementAt(4)); + + var q2 = from x in new[] { "!@#$%^", "C", "AAA", "", "Calling Twice", "SoS", string.Empty } + where !string.IsNullOrEmpty(x) + select x; + Assert.Equal(q2.ElementAt(new Index(4)), q2.ElementAt(new Index(4))); - Assert.Equal(q.ElementAt(4), q.ElementAt(4)); + var q3 = from x in new[] { "!@#$%^", "C", "AAA", "", "Calling Twice", "SoS", string.Empty } + where !string.IsNullOrEmpty(x) + select x; + Assert.Equal(q3.ElementAt(^2), q3.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?[] { 9, 8 }.ElementAt(^3)); + AssertExtensions.Throws("index", () => new int?[] { 9, 8 }.ElementAt(int.MaxValue)); + AssertExtensions.Throws("index", () => new int?[] { 9, 8 }.ElementAt(int.MinValue)); + AssertExtensions.Throws("index", () => new int?[] { 9, 8 }.ElementAt(new Index(int.MaxValue))); + AssertExtensions.Throws("index", () => new int?[] { 9, 8 }.ElementAt(^int.MaxValue)); + AssertExtensions.Throws("index", () => new int[] { 1, 2, 3, 4 }.ElementAt(4)); + AssertExtensions.Throws("index", () => new int[] { 1, 2, 3, 4 }.ElementAt(new Index(4))); + AssertExtensions.Throws("index", () => new int[] { 1, 2, 3, 4 }.ElementAt(^0)); + AssertExtensions.Throws("index", () => new int[] { 1, 2, 3, 4 }.ElementAt(^5)); + AssertExtensions.Throws("index", () => new int[0].ElementAt(0)); + AssertExtensions.Throws("index", () => new int[0].ElementAt(new Index(0))); + AssertExtensions.Throws("index", () => new int[0].ElementAt(^0)); + AssertExtensions.Throws("index", () => new int[0].ElementAt(^1)); AssertExtensions.Throws("index", () => NumberRangeGuaranteedNotCollectionType(-4, 5).ElementAt(-1)); + AssertExtensions.Throws("index", () => NumberRangeGuaranteedNotCollectionType(-4, 5).ElementAt(int.MinValue)); + AssertExtensions.Throws("index", () => NumberRangeGuaranteedNotCollectionType(-4, 5).ElementAt(int.MaxValue)); + AssertExtensions.Throws("index", () => NumberRangeGuaranteedNotCollectionType(-4, 5).ElementAt(^6)); + AssertExtensions.Throws("index", () => NumberRangeGuaranteedNotCollectionType(-4, 5).ElementAt(new Index(int.MaxValue))); + AssertExtensions.Throws("index", () => NumberRangeGuaranteedNotCollectionType(-4, 5).ElementAt(^int.MaxValue)); + AssertExtensions.Throws("index", () => NumberRangeGuaranteedNotCollectionType(5, 5).ElementAt(5)); - AssertExtensions.Throws("index", () => NumberRangeGuaranteedNotCollectionType(0, 0).ElementAt(0)); + AssertExtensions.Throws("index", () => NumberRangeGuaranteedNotCollectionType(5, 5).ElementAt(new Index(5))); + AssertExtensions.Throws("index", () => NumberRangeGuaranteedNotCollectionType(5, 5).ElementAt(^0)); + AssertExtensions.Throws("index", () => NumberRangeGuaranteedNotCollectionType(0, 0).ElementAt(0)); + AssertExtensions.Throws("index", () => NumberRangeGuaranteedNotCollectionType(0, 0).ElementAt(new Index(0))); + AssertExtensions.Throws("index", () => NumberRangeGuaranteedNotCollectionType(0, 0).ElementAt(^0)); + AssertExtensions.Throws("index", () => NumberRangeGuaranteedNotCollectionType(0, 0).ElementAt(^1)); } [Fact] @@ -72,18 +118,20 @@ public void NullableArray_ValidIndex_ReturnsCorrectObject() Assert.Null(source.ElementAt(2)); Assert.Equal(-5, source.ElementAt(3)); - } - [Fact] - public void NullSource_ThrowsArgumentNullException() - { - AssertExtensions.Throws("source", () => ((IEnumerable)null).ElementAt(2)); + 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 Index() + public void NullSource_ThrowsArgumentNullException() { AssertExtensions.Throws("source", () => ((IEnumerable)null).ElementAt(2)); + AssertExtensions.Throws("source", () => ((IEnumerable)null).ElementAt(new Index(2))); + AssertExtensions.Throws("source", () => ((IEnumerable)null).ElementAt(^2)); } } } From ee298f769799ee6aac6adb8f219e2ec53ee8c0b6 Mon Sep 17 00:00:00 2001 From: Dixin Date: Wed, 3 Feb 2021 05:14:24 -0800 Subject: [PATCH 09/35] Implement dotnet/runtime#28776: LINQ APIs for index and range. --- .../tests/ElementAtOrDefaultTests.cs | 34 +++++++++++++++--- .../tests/ElementAtTests.cs | 22 ++++++++++-- .../System.Linq.Queryable/tests/TakeTests.cs | 36 +++++++++++++++++-- 3 files changed, 82 insertions(+), 10 deletions(-) diff --git a/src/libraries/System.Linq.Queryable/tests/ElementAtOrDefaultTests.cs b/src/libraries/System.Linq.Queryable/tests/ElementAtOrDefaultTests.cs index c86d69de260c9e..f6bf5c47d2dfc5 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 c334438c86ab74..bc6662ea007aaf 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 ecafe37a51d837..2dd8a77cf6f6d7 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); } } } From 9be2f22ec9e4d7501b5ab86e5d691e7620eed679 Mon Sep 17 00:00:00 2001 From: Dixin Date: Wed, 3 Feb 2021 06:33:06 -0800 Subject: [PATCH 10/35] Implement dotnet/runtime#28776: LINQ APIs for index and range. --- .../src/System/Linq/CachedReflection.cs | 1 - .../src/System/Linq/Queryable.cs | 1 - .../System.Linq/src/System/Linq/ElementAt.cs | 2 - src/libraries/System.Linq/tests/TakeTests.cs | 1172 +++++++++++++---- 4 files changed, 911 insertions(+), 265 deletions(-) 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 d0bc19dfdc9f08..e7cbb7c3a3b3a2 100644 --- a/src/libraries/System.Linq.Queryable/src/System/Linq/CachedReflection.cs +++ b/src/libraries/System.Linq.Queryable/src/System/Linq/CachedReflection.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 System.Linq.Expressions; using System.Reflection; 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 2efe18e5503576..7f3a996ec5c5e8 100644 --- a/src/libraries/System.Linq.Queryable/src/System/Linq/Queryable.cs +++ b/src/libraries/System.Linq.Queryable/src/System/Linq/Queryable.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; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; diff --git a/src/libraries/System.Linq/src/System/Linq/ElementAt.cs b/src/libraries/System.Linq/src/System/Linq/ElementAt.cs index 77e8dd331e1efe..b902699ea9db85 100644 --- a/src/libraries/System.Linq/src/System/Linq/ElementAt.cs +++ b/src/libraries/System.Linq/src/System/Linq/ElementAt.cs @@ -1,9 +1,7 @@ // 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 System.Diagnostics.CodeAnalysis; namespace System.Linq { diff --git a/src/libraries/System.Linq/tests/TakeTests.cs b/src/libraries/System.Linq/tests/TakeTests.cs index a4a472f544ab51..b5331edce351e3 100644 --- a/src/libraries/System.Linq/tests/TakeTests.cs +++ b/src/libraries/System.Linq/tests/TakeTests.cs @@ -14,23 +14,33 @@ private static IEnumerable GuaranteeNotIList(IEnumerable source) yield return element; } - private static T[] Repeat(Func factory, int count = 5) + private static T[] Repeat(Func factory, int count = 5) { T[] results = new T[count]; - for (int i = 0; i < results.Length; i++) + for (int index = 0; index < results.Length; index++) { - results[i] = factory(); + results[index] = factory(index); } return results; } + private static IEnumerable ToListPartition(IList source) + { + return source.Skip(0); + } + + private static IEnumerable ToEnumerablePartition(IList source) + { + return GuaranteeNotIList(source).Skip(0); + } + [Fact] public void SameResultsRepeatCallsIntQuery() { - var q = Repeat(() => from x in new[] { 9999, 0, 888, -1, 66, -777, 1, 2, -12345 } - where x > int.MinValue - select x); + var q = Repeat(_ => from x in new[] { 9999, 0, 888, -1, 66, -777, 1, 2, -12345 } + where x > int.MinValue + select x); Assert.Equal(q[0].Take(9), q[0].Take(9)); @@ -48,9 +58,9 @@ where x > int.MinValue [Fact] public void SameResultsRepeatCallsIntQueryIList() { - var q = Repeat(() => (from x in new[] { 9999, 0, 888, -1, 66, -777, 1, 2, -12345 } - where x > Int32.MinValue - select x).ToList()); + var q = Repeat(_ => (from x in new[] { 9999, 0, 888, -1, 66, -777, 1, 2, -12345 } + where x > Int32.MinValue + select x).ToList()); Assert.Equal(q[0].Take(9), q[0].Take(9)); @@ -68,9 +78,9 @@ where x > Int32.MinValue [Fact] public void SameResultsRepeatCallsStringQuery() { - var q = Repeat(() => from x in new[] { "!@#$%^", "C", "AAA", "", "Calling Twice", "SoS", string.Empty } - where !string.IsNullOrEmpty(x) - select x); + var q = Repeat(_ => from x in new[] { "!@#$%^", "C", "AAA", "", "Calling Twice", "SoS", string.Empty } + where !string.IsNullOrEmpty(x) + select x); Assert.Equal(q[0].Take(7), q[0].Take(7)); @@ -83,9 +93,9 @@ public void SameResultsRepeatCallsStringQuery() [Fact] public void SameResultsRepeatCallsStringQueryIList() { - var q = Repeat(() => (from x in new[] { "!@#$%^", "C", "AAA", "", "Calling Twice", "SoS", String.Empty } - where !String.IsNullOrEmpty(x) - select x).ToList()); + var q = Repeat(_ => (from x in new[] { "!@#$%^", "C", "AAA", "", "Calling Twice", "SoS", String.Empty } + where !String.IsNullOrEmpty(x) + select x).ToList()); Assert.Equal(q[0].Take(7), q[0].Take(7)); @@ -125,7 +135,7 @@ public void SourceNonEmptyCountNegative() int[] source = { 2, 5, 9, 1 }; Assert.Empty(source.Take(-5)); - Assert.Empty(source.Take(0..^9)); + Assert.Empty(source.Take(^9..0)); } [Fact] @@ -134,7 +144,7 @@ public void SourceNonEmptyCountNegativeNotIList() var source = GuaranteeNotIList(new[] { 2, 5, 9, 1 }); Assert.Empty(source.Take(-5)); - Assert.Empty(source.Take(0..^9)); + Assert.Empty(source.Take(^9..0)); } [Fact] @@ -814,6 +824,35 @@ 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] @@ -827,6 +866,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] @@ -840,6 +908,35 @@ 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] @@ -853,6 +950,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] @@ -863,6 +989,26 @@ 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] @@ -873,34 +1019,82 @@ public void TakeCanOnlyBeOneNotList() 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); + + taken2 = source.Take(^5..3); + Assert.Equal(taken2, taken2); + + taken2 = source.Take(0..^2); + Assert.Equal(taken2, taken2); + + taken2 = source.Take(^5..^2); + Assert.Equal(taken2, taken2); } [Fact] public void RepeatEnumeratingNotList() { var source = GuaranteeNotIList(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); + + taken2 = source.Take(^5..3); + Assert.Equal(taken2, taken2); + + taken2 = source.Take(0..^2); + Assert.Equal(taken2, taken2); + + taken2 = source.Take(^5..^2); + Assert.Equal(taken2, taken2); } [Theory] [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] @@ -908,11 +1102,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).Skip(42).Take(0..int.MaxValue); + 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()); + + taken2 = NumberRangeGuaranteedNotCollectionType(1, 100).Skip(42).Take(^int.MaxValue..int.MaxValue); + 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()); + + taken2 = NumberRangeGuaranteedNotCollectionType(1, 100).Skip(42).Take(int.MaxValue..^0); + 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()); + + taken2 = NumberRangeGuaranteedNotCollectionType(1, 100).Skip(42).Take(^int.MaxValue..^0); + 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()); } [Theory] @@ -928,10 +1146,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); + + partition2 = NumberRangeGuaranteedNotCollectionType(1, totalCount).Take(^Math.Max(totalCount - skip, 0)..end); + Assert.Equal(expected, partition2.Count()); + Assert.Equal(expected, partition2.Select(i => i).Count()); + Assert.Equal(expected, partition2.Select(i => i).ToArray().Length); + + partition2 = NumberRangeGuaranteedNotCollectionType(1, totalCount).Take(skip..^Math.Max(totalCount - end, 0)); + Assert.Equal(expected, partition2.Count()); + Assert.Equal(expected, partition2.Select(i => i).Count()); + Assert.Equal(expected, partition2.Select(i => i).ToArray().Length); + + partition2 = NumberRangeGuaranteedNotCollectionType(1, totalCount).Take(^Math.Max(totalCount - skip, 0)..^Math.Max(totalCount - end, 0)); + Assert.Equal(expected, partition2.Count()); + Assert.Equal(expected, partition2.Select(i => i).Count()); + Assert.Equal(expected, partition2.Select(i => i).ToArray().Length); } [Theory] @@ -941,14 +1190,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)); + + 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)); + + partition2 = ForceNotCollection(source).Take(^Math.Max(source.Length - skip, 0)..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)); - Assert.Equal(first, partition.FirstOrDefault()); - Assert.Equal(first, partition.ElementAtOrDefault(0)); - Assert.Equal(last, partition.LastOrDefault()); - Assert.Equal(last, partition.ElementAtOrDefault(partition.Count() - 1)); + partition2 = ForceNotCollection(source).Take(skip..^Math.Max(source.Length - end, 0)); + + Assert.Equal(first, partition2.FirstOrDefault()); + Assert.Equal(first, partition2.ElementAtOrDefault(0)); + Assert.Equal(last, partition2.LastOrDefault()); + Assert.Equal(last, partition2.ElementAtOrDefault(partition2.Count() - 1)); + + partition2 = ForceNotCollection(source).Take(^Math.Max(source.Length - skip, 0)..^Math.Max(source.Length - end, 0)); + + Assert.Equal(first, partition2.FirstOrDefault()); + Assert.Equal(first, partition2.ElementAtOrDefault(0)); + Assert.Equal(last, partition2.LastOrDefault()); + Assert.Equal(last, partition2.ElementAtOrDefault(partition2.Count() - 1)); } [Theory] @@ -956,14 +1243,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])); } } @@ -976,283 +1297,612 @@ public void ElementAtOfLazySkipTakeChain(IEnumerable source, int skip, int [InlineData(2, 3)] public void DisposeSource(int sourceCount, int count) { - int state = 0; + int[] state = new int[5]; - var source = new DelegateIterator( - moveNext: () => ++state <= sourceCount, + var source = Repeat(index => new DelegateIterator( + moveNext: () => ++state[index] <= sourceCount, current: () => 0, - dispose: () => state = -1); + dispose: () => state[index] = -1)); - 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); + Assert.Equal(expected, state[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()); + Assert.Equal(expected, state[1]); + + IEnumerator iterator2 = source[2].Take(^Math.Max(sourceCount, end)..end).GetEnumerator(); + Assert.All(Enumerable.Range(0, Math.Min(sourceCount, Math.Max(0, count))), _ => Assert.True(iterator2.MoveNext())); + Assert.False(iterator2.MoveNext()); + Assert.Equal(expected, state[2]); + + IEnumerator iterator3 = source[3].Take(0..^Math.Max(0, sourceCount - end)).GetEnumerator(); + Assert.All(Enumerable.Range(0, Math.Min(sourceCount, Math.Max(0, count))), _ => Assert.True(iterator3.MoveNext())); + Assert.False(iterator3.MoveNext()); + Assert.Equal(expected, state[3]); + + IEnumerator iterator4 = source[4].Take(^Math.Max(sourceCount, end)..^Math.Max(0, sourceCount - end)).GetEnumerator(); + Assert.All(Enumerable.Range(0, Math.Min(sourceCount, Math.Max(0, count))), _ => Assert.True(iterator4.MoveNext())); + Assert.False(iterator4.MoveNext()); + Assert.Equal(expected, state[4]); + } + + [Fact] + public void OutOfBoundNoException() + { + var 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, GuaranteeNotIList(source).Take(0..6)); + Assert.Equal(source, GuaranteeNotIList(source).Take(0..int.MaxValue)); + + Assert.Equal(new int[] { 1, 2, 3, 4 }, GuaranteeNotIList(source).Take(^10..4)); + Assert.Equal(new int[] { 1, 2, 3, 4 }, GuaranteeNotIList(source).Take(^int.MaxValue..4)); + Assert.Equal(source, GuaranteeNotIList(source).Take(^10..6)); + Assert.Equal(source, GuaranteeNotIList(source).Take(^int.MaxValue..6)); + Assert.Equal(source, GuaranteeNotIList(source).Take(^10..int.MaxValue)); + Assert.Equal(source, GuaranteeNotIList(source).Take(^int.MaxValue..int.MaxValue)); + + Assert.Empty(GuaranteeNotIList(source).Take(0..^6)); + Assert.Empty(GuaranteeNotIList(source).Take(0..^int.MaxValue)); + Assert.Empty(GuaranteeNotIList(source).Take(4..^6)); + Assert.Empty(GuaranteeNotIList(source).Take(4..^int.MaxValue)); + Assert.Empty(GuaranteeNotIList(source).Take(6..^6)); + Assert.Empty(GuaranteeNotIList(source).Take(6..^int.MaxValue)); + Assert.Empty(GuaranteeNotIList(source).Take(int.MaxValue..^6)); + Assert.Empty(GuaranteeNotIList(source).Take(int.MaxValue..^int.MaxValue)); + + Assert.Equal(new int[] { 1, 2, 3, 4 }, GuaranteeNotIList(source).Take(^10..^1)); + Assert.Equal(new int[] { 1, 2, 3, 4 }, GuaranteeNotIList(source).Take(^int.MaxValue..^1)); + Assert.Empty(GuaranteeNotIList(source).Take(^0..^6)); + Assert.Empty(GuaranteeNotIList(source).Take(^1..^6)); + Assert.Empty(GuaranteeNotIList(source).Take(^6..^6)); + Assert.Empty(GuaranteeNotIList(source).Take(^10..^6)); + Assert.Empty(GuaranteeNotIList(source).Take(^int.MaxValue..^6)); + Assert.Empty(GuaranteeNotIList(source).Take(^0..^int.MaxValue)); + Assert.Empty(GuaranteeNotIList(source).Take(^1..^int.MaxValue)); + Assert.Empty(GuaranteeNotIList(source).Take(^6..^int.MaxValue)); + Assert.Empty(GuaranteeNotIList(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 NonEmptySourceTests() + public void MutableSourceNotList() + { + var source1 = new List() { 0, 1, 2, 3, 4 }; + var query1 = GuaranteeNotIList(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 = GuaranteeNotIList(source1).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 = GuaranteeNotIList(source1).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 = GuaranteeNotIList(source1).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_ConsistentWithCountable() { int[] source = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; // Multiple elements in the middle. - Assert.True(source.Take(^9..5).ToArray().SequenceEqual(source[^9..5])); - Assert.True(source.Take(2..7).ToArray().SequenceEqual(source[2..7])); - Assert.True(source.Take(2..^4).ToArray().SequenceEqual(source[2..^4])); - Assert.True(source.Take(^7..^4).ToArray().SequenceEqual(source[^7..^4])); - - Assert.True(source.Hide().Take(^9..5).ToArray().SequenceEqual(source[^9..5])); - Assert.True(source.Hide().Take(2..7).ToArray().SequenceEqual(source[2..7])); - Assert.True(source.Hide().Take(2..^4).ToArray().SequenceEqual(source[2..^4])); - Assert.True(source.Hide().Take(^7..^4).ToArray().SequenceEqual(source[^7..^4])); - - // Rang with one index. - Assert.True(source.Take(^9..).ToArray().SequenceEqual(source[^9..])); - Assert.True(source.Take(2..).ToArray().SequenceEqual(source[2..])); - Assert.True(source.Take(..^4).ToArray().SequenceEqual(source[..^4])); - Assert.True(source.Take(..6).ToArray().SequenceEqual(source[..6])); - - Assert.True(source.Hide().Take(^9..).ToArray().SequenceEqual(source[^9..])); - Assert.True(source.Hide().Take(2..).ToArray().SequenceEqual(source[2..])); - Assert.True(source.Hide().Take(..^4).ToArray().SequenceEqual(source[..^4])); - Assert.True(source.Hide().Take(..6).ToArray().SequenceEqual(source[..6])); + 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.True(source.Take(..).ToArray().SequenceEqual(source[..])); + 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)); - Assert.True(source.Hide().Take(..).ToArray().SequenceEqual(source[..])); + // 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_ConsistentWithCountable_NotList() + { + int[] source = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + + // Multiple elements in the middle. + Assert.Equal(source[^9..5], GuaranteeNotIList(source).Take(^9..5)); + Assert.Equal(source[2..7], GuaranteeNotIList(source).Take(2..7)); + Assert.Equal(source[2..^4], GuaranteeNotIList(source).Take(2..^4)); + Assert.Equal(source[^7..^4], GuaranteeNotIList(source).Take(^7..^4)); + + // Range with default index. + Assert.Equal(source[^9..], GuaranteeNotIList(source).Take(^9..)); + Assert.Equal(source[2..], GuaranteeNotIList(source).Take(2..)); + Assert.Equal(source[..^4], GuaranteeNotIList(source).Take(..^4)); + Assert.Equal(source[..6], GuaranteeNotIList(source).Take(..6)); + + // All. + Assert.Equal(source[..], GuaranteeNotIList(source).Take(..)); // Single element in the middle. - Assert.True(source.Take(^9..2).ToArray().SequenceEqual(source[^9..2])); - Assert.True(source.Take(2..3).ToArray().SequenceEqual(source[2..3])); - Assert.True(source.Take(2..^7).ToArray().SequenceEqual(source[2..^7])); - Assert.True(source.Take(^5..^4).ToArray().SequenceEqual(source[^5..^4])); + Assert.Equal(source[^9..2], GuaranteeNotIList(source).Take(^9..2)); + Assert.Equal(source[2..3], GuaranteeNotIList(source).Take(2..3)); + Assert.Equal(source[2..^7], GuaranteeNotIList(source).Take(2..^7)); + Assert.Equal(source[^5..^4], GuaranteeNotIList(source).Take(^5..^4)); + + // Single element at start. + Assert.Equal(source[^10..1], GuaranteeNotIList(source).Take(^10..1)); + Assert.Equal(source[0..1], GuaranteeNotIList(source).Take(0..1)); + Assert.Equal(source[0..^9], GuaranteeNotIList(source).Take(0..^9)); + Assert.Equal(source[^10..^9], GuaranteeNotIList(source).Take(^10..^9)); + + // Single element at end. + Assert.Equal(source[^1..10], GuaranteeNotIList(source).Take(^1..10)); + Assert.Equal(source[9..10], GuaranteeNotIList(source).Take(9..10)); + Assert.Equal(source[9..^0], GuaranteeNotIList(source).Take(9..^0)); + Assert.Equal(source[^1..^0], GuaranteeNotIList(source).Take(^1..^0)); + + // No element. + Assert.Equal(source[3..3], GuaranteeNotIList(source).Take(3..3)); + Assert.Equal(source[6..^4], GuaranteeNotIList(source).Take(6..^4)); + Assert.Equal(source[3..^7], GuaranteeNotIList(source).Take(3..^7)); + Assert.Equal(source[^3..7], GuaranteeNotIList(source).Take(^3..7)); + Assert.Equal(source[^6..^6], GuaranteeNotIList(source).Take(^6..^6)); + } - Assert.True(source.Hide().Take(^9..2).ToArray().SequenceEqual(source[^9..2])); - Assert.True(source.Hide().Take(2..3).ToArray().SequenceEqual(source[2..3])); - Assert.True(source.Hide().Take(2..^7).ToArray().SequenceEqual(source[2..^7])); - Assert.True(source.Hide().Take(^5..^4).ToArray().SequenceEqual(source[^5..^4])); + [Fact] + public void NonEmptySource_ConsistentWithCountable_ListPartition() + { + int[] source = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + + // Multiple elements in the middle. + Assert.Equal(source[^9..5], ToListPartition(source).Take(^9..5)); + Assert.Equal(source[2..7], ToListPartition(source).Take(2..7)); + Assert.Equal(source[2..^4], ToListPartition(source).Take(2..^4)); + Assert.Equal(source[^7..^4], ToListPartition(source).Take(^7..^4)); + + // Range with default index. + Assert.Equal(source[^9..], ToListPartition(source).Take(^9..)); + Assert.Equal(source[2..], ToListPartition(source).Take(2..)); + Assert.Equal(source[..^4], ToListPartition(source).Take(..^4)); + Assert.Equal(source[..6], ToListPartition(source).Take(..6)); + + // All. + Assert.Equal(source[..], ToListPartition(source).Take(..)); + + // Single element in the middle. + Assert.Equal(source[^9..2], ToListPartition(source).Take(^9..2)); + Assert.Equal(source[2..3], ToListPartition(source).Take(2..3)); + Assert.Equal(source[2..^7], ToListPartition(source).Take(2..^7)); + Assert.Equal(source[^5..^4], ToListPartition(source).Take(^5..^4)); // Single element at start. - Assert.True(source.Take(^10..1).ToArray().SequenceEqual(source[^10..1])); - Assert.True(source.Take(0..1).ToArray().SequenceEqual(source[0..1])); - Assert.True(source.Take(0..^9).ToArray().SequenceEqual(source[0..^9])); - Assert.True(source.Take(^10..^9).ToArray().SequenceEqual(source[^10..^9])); + Assert.Equal(source[^10..1], ToListPartition(source).Take(^10..1)); + Assert.Equal(source[0..1], ToListPartition(source).Take(0..1)); + Assert.Equal(source[0..^9], ToListPartition(source).Take(0..^9)); + Assert.Equal(source[^10..^9], ToListPartition(source).Take(^10..^9)); + + // Single element at end. + Assert.Equal(source[^1..10], ToListPartition(source).Take(^1..10)); + Assert.Equal(source[9..10], ToListPartition(source).Take(9..10)); + Assert.Equal(source[9..^0], ToListPartition(source).Take(9..^0)); + Assert.Equal(source[^1..^0], ToListPartition(source).Take(^1..^0)); + + // No element. + Assert.Equal(source[3..3], ToListPartition(source).Take(3..3)); + Assert.Equal(source[6..^4], ToListPartition(source).Take(6..^4)); + Assert.Equal(source[3..^7], ToListPartition(source).Take(3..^7)); + Assert.Equal(source[^3..7], ToListPartition(source).Take(^3..7)); + Assert.Equal(source[^6..^6], ToListPartition(source).Take(^6..^6)); + } + + [Fact] + public void NonEmptySource_ConsistentWithCountable_EnumerablePartition() + { + int[] source = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + + // Multiple elements in the middle. + Assert.Equal(source[^9..5], ToEnumerablePartition(source).Take(^9..5)); + Assert.Equal(source[2..7], ToEnumerablePartition(source).Take(2..7)); + Assert.Equal(source[2..^4], ToEnumerablePartition(source).Take(2..^4)); + Assert.Equal(source[^7..^4], ToEnumerablePartition(source).Take(^7..^4)); - Assert.True(source.Hide().Take(^10..1).ToArray().SequenceEqual(source[^10..1])); - Assert.True(source.Hide().Take(0..1).ToArray().SequenceEqual(source[0..1])); - Assert.True(source.Hide().Take(0..^9).ToArray().SequenceEqual(source[0..^9])); - Assert.True(source.Hide().Take(^10..^9).ToArray().SequenceEqual(source[^10..^9])); + // Range with default index. + Assert.Equal(source[^9..], ToEnumerablePartition(source).Take(^9..)); + Assert.Equal(source[2..], ToEnumerablePartition(source).Take(2..)); + Assert.Equal(source[..^4], ToEnumerablePartition(source).Take(..^4)); + Assert.Equal(source[..6], ToEnumerablePartition(source).Take(..6)); + + // All. + Assert.Equal(source[..], ToEnumerablePartition(source).Take(..)); + + // Single element in the middle. + Assert.Equal(source[^9..2], ToEnumerablePartition(source).Take(^9..2)); + Assert.Equal(source[2..3], ToEnumerablePartition(source).Take(2..3)); + Assert.Equal(source[2..^7], ToEnumerablePartition(source).Take(2..^7)); + Assert.Equal(source[^5..^4], ToEnumerablePartition(source).Take(^5..^4)); + + // Single element at start. + Assert.Equal(source[^10..1], ToEnumerablePartition(source).Take(^10..1)); + Assert.Equal(source[0..1], ToEnumerablePartition(source).Take(0..1)); + Assert.Equal(source[0..^9], ToEnumerablePartition(source).Take(0..^9)); + Assert.Equal(source[^10..^9], ToEnumerablePartition(source).Take(^10..^9)); // Single element at end. - Assert.True(source.Take(^1..10).ToArray().SequenceEqual(source[^1..10])); - Assert.True(source.Take(9..10).ToArray().SequenceEqual(source[9..10])); - Assert.True(source.Take(9..^0).ToArray().SequenceEqual(source[9..^0])); - Assert.True(source.Take(^1..^0).ToArray().SequenceEqual(source[^1..^0])); + Assert.Equal(source[^1..10], ToEnumerablePartition(source).Take(^1..10)); + Assert.Equal(source[9..10], ToEnumerablePartition(source).Take(9..10)); + Assert.Equal(source[9..^0], ToEnumerablePartition(source).Take(9..^0)); + Assert.Equal(source[^1..^0], ToEnumerablePartition(source).Take(^1..^0)); + + // No element. + Assert.Equal(source[3..3], ToEnumerablePartition(source).Take(3..3)); + Assert.Equal(source[6..^4], ToEnumerablePartition(source).Take(6..^4)); + Assert.Equal(source[3..^7], ToEnumerablePartition(source).Take(3..^7)); + Assert.Equal(source[^3..7], ToEnumerablePartition(source).Take(^3..7)); + Assert.Equal(source[^6..^6], ToEnumerablePartition(source).Take(^6..^6)); + } + + [Fact] + public void NonEmptySource_DoNotThrowException() + { + int[] source = { 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(GuaranteeNotIList(source).Take(3..2)); + Assert.Empty(GuaranteeNotIList(source).Take(6..^5)); + Assert.Empty(GuaranteeNotIList(source).Take(3..^8)); + Assert.Empty(GuaranteeNotIList(source).Take(^6..^7)); + } - Assert.True(source.Hide().Take(^1..10).ToArray().SequenceEqual(source[^1..10])); - Assert.True(source.Hide().Take(9..10).ToArray().SequenceEqual(source[9..10])); - Assert.True(source.Hide().Take(9..^0).ToArray().SequenceEqual(source[9..^0])); - Assert.True(source.Hide().Take(^1..^0).ToArray().SequenceEqual(source[^1..^0])); + [Fact] + public void NonEmptySource_DoNotThrowException_ListPartition() + { + int[] source = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + + Assert.Empty(ToListPartition(source).Take(3..2)); + Assert.Empty(ToListPartition(source).Take(6..^5)); + Assert.Empty(ToListPartition(source).Take(3..^8)); + Assert.Empty(ToListPartition(source).Take(^6..^7)); + } + + [Fact] + public void NonEmptySource_DoNotThrowException_EnumerablePartition() + { + int[] source = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + + Assert.Empty(ToEnumerablePartition(source).Take(3..2)); + Assert.Empty(ToEnumerablePartition(source).Take(6..^5)); + Assert.Empty(ToEnumerablePartition(source).Take(3..^8)); + Assert.Empty(ToEnumerablePartition(source).Take(^6..^7)); + } + + [Fact] + public void EmptySource_DoNotThrowException() + { + int[] source = { }; + + // 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.True(source.Take(3..3).ToArray().SequenceEqual(source[3..3])); - Assert.True(source.Take(6..^4).ToArray().SequenceEqual(source[6..^4])); - Assert.True(source.Take(3..^7).ToArray().SequenceEqual(source[3..^7])); - Assert.True(source.Take(^3..7).ToArray().SequenceEqual(source[^3..7])); - Assert.True(source.Take(^6..^6).ToArray().SequenceEqual(source[^6..^6])); - - Assert.True(source.Hide().Take(3..3).ToArray().SequenceEqual(source[3..3])); - Assert.True(source.Hide().Take(6..^4).ToArray().SequenceEqual(source[6..^4])); - Assert.True(source.Hide().Take(3..^7).ToArray().SequenceEqual(source[3..^7])); - Assert.True(source.Hide().Take(^3..7).ToArray().SequenceEqual(source[^3..7])); - Assert.True(source.Hide().Take(^6..^6).ToArray().SequenceEqual(source[^6..^6])); + 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. - AssertExtensions.Throws(() => source[3..2].ToArray()); - Assert.False(source.Take(3..2).Any()); - AssertExtensions.Throws(() => source[6..^5].ToArray()); - Assert.False(source.Take(6..^5).Any()); - AssertExtensions.Throws(() => source[3..^8].ToArray()); - Assert.False(source.Take(3..^8).Any()); - AssertExtensions.Throws(() => source[^6..^7].ToArray()); - Assert.False(source.Take(^6..^7).Any()); - - AssertExtensions.Throws(() => source[3..2].ToArray()); - Assert.False(source.Hide().Take(3..2).Any()); - AssertExtensions.Throws(() => source[6..^5].ToArray()); - Assert.False(source.Hide().Take(6..^5).Any()); - AssertExtensions.Throws(() => source[3..^8].ToArray()); - Assert.False(source.Hide().Take(3..^8).Any()); - AssertExtensions.Throws(() => source[^6..^7].ToArray()); - Assert.False(source.Hide().Take(^6..^7).Any()); + 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 EmptySourceTests() + public void EmptySource_DoNotThrowException_NotList() { int[] source = { }; // Multiple elements in the middle. - AssertExtensions.Throws(() => source[^9..5].ToArray()); - Assert.False(source.Take(^9..5).Any()); - AssertExtensions.Throws(() => source[2..7].ToArray()); - Assert.False(source.Take(2..7).Any()); - AssertExtensions.Throws(() => source[2..^4].ToArray()); - Assert.False(source.Take(2..^4).Any()); - AssertExtensions.Throws(() => source[^7..^4].ToArray()); - Assert.False(source.Take(^7..^4).Any()); - - AssertExtensions.Throws(() => source[^9..5].ToArray()); - Assert.False(source.Hide().Take(^9..5).Any()); - AssertExtensions.Throws(() => source[2..7].ToArray()); - Assert.False(source.Hide().Take(2..7).Any()); - AssertExtensions.Throws(() => source[2..^4].ToArray()); - Assert.False(source.Hide().Take(2..^4).Any()); - AssertExtensions.Throws(() => source[^7..^4].ToArray()); - Assert.False(source.Hide().Take(^7..^4).Any()); - - // Rang with one index. - AssertExtensions.Throws(() => source[^9..].ToArray()); - Assert.False(source.Take(^9..).Any()); - AssertExtensions.Throws(() => source[2..].ToArray()); - Assert.False(source.Take(2..).Any()); - AssertExtensions.Throws(() => source[..^4].ToArray()); - Assert.False(source.Take(..^4).Any()); - AssertExtensions.Throws(() => source[..6].ToArray()); - Assert.False(source.Take(..6).Any()); - - AssertExtensions.Throws(() => source[^9..].ToArray()); - Assert.False(source.Hide().Take(^9..).Any()); - AssertExtensions.Throws(() => source[2..].ToArray()); - Assert.False(source.Hide().Take(2..).Any()); - AssertExtensions.Throws(() => source[..^4].ToArray()); - Assert.False(source.Hide().Take(..^4).Any()); - AssertExtensions.Throws(() => source[..6].ToArray()); - Assert.False(source.Hide().Take(..6).Any()); + Assert.Empty(GuaranteeNotIList(source).Take(^9..5)); + Assert.Empty(GuaranteeNotIList(source).Take(2..7)); + Assert.Empty(GuaranteeNotIList(source).Take(2..^4)); + Assert.Empty(GuaranteeNotIList(source).Take(^7..^4)); + + // Range with default index. + Assert.Empty(GuaranteeNotIList(source).Take(^9..)); + Assert.Empty(GuaranteeNotIList(source).Take(2..)); + Assert.Empty(GuaranteeNotIList(source).Take(..^4)); + Assert.Empty(GuaranteeNotIList(source).Take(..6)); // All. - var xx = source[..]; - Assert.True(source.Take(..).ToArray().SequenceEqual(source[..])); + Assert.Equal(source[..], GuaranteeNotIList(source).Take(..)); + + // Single element in the middle. + Assert.Empty(GuaranteeNotIList(source).Take(^9..2)); + Assert.Empty(GuaranteeNotIList(source).Take(2..3)); + Assert.Empty(GuaranteeNotIList(source).Take(2..^7)); + Assert.Empty(GuaranteeNotIList(source).Take(^5..^4)); + + // Single element at start. + Assert.Empty(GuaranteeNotIList(source).Take(^10..1)); + Assert.Empty(GuaranteeNotIList(source).Take(0..1)); + Assert.Empty(GuaranteeNotIList(source).Take(0..^9)); + Assert.Empty(GuaranteeNotIList(source).Take(^10..^9)); + + // Single element at end. + Assert.Empty(GuaranteeNotIList(source).Take(^1..^10)); + Assert.Empty(GuaranteeNotIList(source).Take(9..10)); + Assert.Empty(GuaranteeNotIList(source).Take(9..^9)); + Assert.Empty(GuaranteeNotIList(source).Take(^1..^9)); - Assert.True(source.Hide().Take(..).ToArray().SequenceEqual(source[..])); + // No element. + Assert.Empty(GuaranteeNotIList(source).Take(3..3)); + Assert.Empty(GuaranteeNotIList(source).Take(6..^4)); + Assert.Empty(GuaranteeNotIList(source).Take(3..^7)); + Assert.Empty(GuaranteeNotIList(source).Take(^3..7)); + Assert.Empty(GuaranteeNotIList(source).Take(^6..^6)); + + // Invalid range. + Assert.Empty(GuaranteeNotIList(source).Take(3..2)); + Assert.Empty(GuaranteeNotIList(source).Take(6..^5)); + Assert.Empty(GuaranteeNotIList(source).Take(3..^8)); + Assert.Empty(GuaranteeNotIList(source).Take(^6..^7)); + } + + [Fact] + public void EmptySource_DoNotThrowException_ListPartition() + { + int[] source = { }; + + // Multiple elements in the middle. + Assert.Empty(ToListPartition(source).Take(^9..5)); + Assert.Empty(ToListPartition(source).Take(2..7)); + Assert.Empty(ToListPartition(source).Take(2..^4)); + Assert.Empty(ToListPartition(source).Take(^7..^4)); + + // Range with default index. + Assert.Empty(ToListPartition(source).Take(^9..)); + Assert.Empty(ToListPartition(source).Take(2..)); + Assert.Empty(ToListPartition(source).Take(..^4)); + Assert.Empty(ToListPartition(source).Take(..6)); + + // All. + Assert.Equal(source[..], ToListPartition(source).Take(..)); // Single element in the middle. - AssertExtensions.Throws(() => source[^9..2].ToArray()); - Assert.False(source.Take(^9..2).Any()); - AssertExtensions.Throws(() => source[2..3].ToArray()); - Assert.False(source.Take(2..3).Any()); - AssertExtensions.Throws(() => source[2..^7].ToArray()); - Assert.False(source.Take(2..^7).Any()); - AssertExtensions.Throws(() => source[^5..^4].ToArray()); - Assert.False(source.Take(^5..^4).Any()); - - AssertExtensions.Throws(() => source[^9..2].ToArray()); - Assert.False(source.Hide().Take(^9..2).Any()); - AssertExtensions.Throws(() => source[2..3].ToArray()); - Assert.False(source.Hide().Take(2..3).Any()); - AssertExtensions.Throws(() => source[2..^7].ToArray()); - Assert.False(source.Hide().Take(2..^7).Any()); - AssertExtensions.Throws(() => source[^5..^4].ToArray()); - Assert.False(source.Hide().Take(^5..^4).Any()); + Assert.Empty(ToListPartition(source).Take(^9..2)); + Assert.Empty(ToListPartition(source).Take(2..3)); + Assert.Empty(ToListPartition(source).Take(2..^7)); + Assert.Empty(ToListPartition(source).Take(^5..^4)); // Single element at start. - AssertExtensions.Throws(() => source[^10..1].ToArray()); - Assert.False(source.Take(^10..1).Any()); - AssertExtensions.Throws(() => source[0..1].ToArray()); - Assert.False(source.Take(0..1).Any()); - AssertExtensions.Throws(() => source[0..^9].ToArray()); - Assert.False(source.Take(0..^9).Any()); - AssertExtensions.Throws(() => source[^10..^9].ToArray()); - Assert.False(source.Take(^10..^9).Any()); - - AssertExtensions.Throws(() => source[^10..1].ToArray()); - Assert.False(source.Hide().Take(^10..1).Any()); - AssertExtensions.Throws(() => source[0..1].ToArray()); - Assert.False(source.Hide().Take(0..1).Any()); - AssertExtensions.Throws(() => source[0..^9].ToArray()); - Assert.False(source.Hide().Take(0..^9).Any()); - AssertExtensions.Throws(() => source[^10..^9].ToArray()); - Assert.False(source.Hide().Take(^10..^9).Any()); + Assert.Empty(ToListPartition(source).Take(^10..1)); + Assert.Empty(ToListPartition(source).Take(0..1)); + Assert.Empty(ToListPartition(source).Take(0..^9)); + Assert.Empty(ToListPartition(source).Take(^10..^9)); // Single element at end. - AssertExtensions.Throws(() => source[^1..10].ToArray()); - Assert.False(source.Take(^1..^10).Any()); - AssertExtensions.Throws(() => source[9..10].ToArray()); - Assert.False(source.Take(9..10).Any()); - AssertExtensions.Throws(() => source[9..^0].ToArray()); - Assert.False(source.Take(9..^9).Any()); - AssertExtensions.Throws(() => source[^1..^0].ToArray()); - Assert.False(source.Take(^1..^9).Any()); - - AssertExtensions.Throws(() => source[^1..10].ToArray()); - Assert.False(source.Hide().Take(^1..^10).Any()); - AssertExtensions.Throws(() => source[9..10].ToArray()); - Assert.False(source.Hide().Take(9..10).Any()); - AssertExtensions.Throws(() => source[9..^0].ToArray()); - Assert.False(source.Hide().Take(9..^9).Any()); - AssertExtensions.Throws(() => source[^1..^0].ToArray()); - Assert.False(source.Hide().Take(^1..^9).Any()); + Assert.Empty(ToListPartition(source).Take(^1..^10)); + Assert.Empty(ToListPartition(source).Take(9..10)); + Assert.Empty(ToListPartition(source).Take(9..^9)); + Assert.Empty(ToListPartition(source).Take(^1..^9)); // No element. - AssertExtensions.Throws(() => source[3..3].ToArray()); - Assert.False(source.Take(3..3).Any()); - AssertExtensions.Throws(() => source[6..^4].ToArray()); - Assert.False(source.Take(6..^4).Any()); - AssertExtensions.Throws(() => source[3..^7].ToArray()); - Assert.False(source.Take(3..^7).Any()); - AssertExtensions.Throws(() => source[^3..7].ToArray()); - Assert.False(source.Take(^3..7).Any()); - AssertExtensions.Throws(() => source[^6..^6].ToArray()); - Assert.False(source.Take(^6..^6).Any()); - - AssertExtensions.Throws(() => source[3..3].ToArray()); - Assert.False(source.Hide().Take(3..3).Any()); - AssertExtensions.Throws(() => source[6..^4].ToArray()); - Assert.False(source.Hide().Take(6..^4).Any()); - AssertExtensions.Throws(() => source[3..^7].ToArray()); - Assert.False(source.Hide().Take(3..^7).Any()); - AssertExtensions.Throws(() => source[^3..7].ToArray()); - Assert.False(source.Hide().Take(^3..7).Any()); - AssertExtensions.Throws(() => source[^6..^6].ToArray()); - Assert.False(source.Hide().Take(^6..^6).Any()); + Assert.Empty(ToListPartition(source).Take(3..3)); + Assert.Empty(ToListPartition(source).Take(6..^4)); + Assert.Empty(ToListPartition(source).Take(3..^7)); + Assert.Empty(ToListPartition(source).Take(^3..7)); + Assert.Empty(ToListPartition(source).Take(^6..^6)); // Invalid range. - AssertExtensions.Throws(() => source[3..2].ToArray()); - Assert.False(source.Take(3..2).Any()); - AssertExtensions.Throws(() => source[6..^5].ToArray()); - Assert.False(source.Take(6..^5).Any()); - AssertExtensions.Throws(() => source[3..^8].ToArray()); - Assert.False(source.Take(3..^8).Any()); - AssertExtensions.Throws(() => source[^6..^7].ToArray()); - Assert.False(source.Take(^6..^7).Any()); - - AssertExtensions.Throws(() => source[3..2].ToArray()); - Assert.False(source.Hide().Take(3..2).Any()); - AssertExtensions.Throws(() => source[6..^5].ToArray()); - Assert.False(source.Hide().Take(6..^5).Any()); - AssertExtensions.Throws(() => source[3..^8].ToArray()); - Assert.False(source.Hide().Take(3..^8).Any()); - AssertExtensions.Throws(() => source[^6..^7].ToArray()); - Assert.False(source.Hide().Take(^6..^7).Any()); + Assert.Empty(ToListPartition(source).Take(3..2)); + Assert.Empty(ToListPartition(source).Take(6..^5)); + Assert.Empty(ToListPartition(source).Take(3..^8)); + Assert.Empty(ToListPartition(source).Take(^6..^7)); } - } - public static class X - { - public static IEnumerable Hide(this IEnumerable source) + [Fact] + public void EmptySource_DoNotThrowException_EnumerablePartition() { - foreach (T value in source) - { - yield return value; - } + int[] source = { }; + + // Multiple elements in the middle. + Assert.Empty(ToEnumerablePartition(source).Take(^9..5)); + Assert.Empty(ToEnumerablePartition(source).Take(2..7)); + Assert.Empty(ToEnumerablePartition(source).Take(2..^4)); + Assert.Empty(ToEnumerablePartition(source).Take(^7..^4)); + + // Range with default index. + Assert.Empty(ToEnumerablePartition(source).Take(^9..)); + Assert.Empty(ToEnumerablePartition(source).Take(2..)); + Assert.Empty(ToEnumerablePartition(source).Take(..^4)); + Assert.Empty(ToEnumerablePartition(source).Take(..6)); + + // All. + Assert.Equal(source[..], ToEnumerablePartition(source).Take(..)); + + // Single element in the middle. + Assert.Empty(ToEnumerablePartition(source).Take(^9..2)); + Assert.Empty(ToEnumerablePartition(source).Take(2..3)); + Assert.Empty(ToEnumerablePartition(source).Take(2..^7)); + Assert.Empty(ToEnumerablePartition(source).Take(^5..^4)); + + // Single element at start. + Assert.Empty(ToEnumerablePartition(source).Take(^10..1)); + Assert.Empty(ToEnumerablePartition(source).Take(0..1)); + Assert.Empty(ToEnumerablePartition(source).Take(0..^9)); + Assert.Empty(ToEnumerablePartition(source).Take(^10..^9)); + + // Single element at end. + Assert.Empty(ToEnumerablePartition(source).Take(^1..^10)); + Assert.Empty(ToEnumerablePartition(source).Take(9..10)); + Assert.Empty(ToEnumerablePartition(source).Take(9..^9)); + Assert.Empty(ToEnumerablePartition(source).Take(^1..^9)); + + // No element. + Assert.Empty(ToEnumerablePartition(source).Take(3..3)); + Assert.Empty(ToEnumerablePartition(source).Take(6..^4)); + Assert.Empty(ToEnumerablePartition(source).Take(3..^7)); + Assert.Empty(ToEnumerablePartition(source).Take(^3..7)); + Assert.Empty(ToEnumerablePartition(source).Take(^6..^6)); + + // Invalid range. + Assert.Empty(ToEnumerablePartition(source).Take(3..2)); + Assert.Empty(ToEnumerablePartition(source).Take(6..^5)); + Assert.Empty(ToEnumerablePartition(source).Take(3..^8)); + Assert.Empty(ToEnumerablePartition(source).Take(^6..^7)); } } } From 1cdf0b82f76295819f79fa7a18c5a08bb8d7a357 Mon Sep 17 00:00:00 2001 From: Dixin Date: Wed, 3 Feb 2021 11:55:41 -0800 Subject: [PATCH 11/35] Implement dotnet/runtime#28776: LINQ APIs for index and range. --- .../tests/ElementAtOrDefaultTests.cs | 36 +- .../System.Linq/tests/ElementAtTests.cs | 36 +- .../System.Linq/tests/EnumerableTests.cs | 25 + src/libraries/System.Linq/tests/TakeTests.cs | 771 +++++++++--------- 4 files changed, 412 insertions(+), 456 deletions(-) diff --git a/src/libraries/System.Linq/tests/ElementAtOrDefaultTests.cs b/src/libraries/System.Linq/tests/ElementAtOrDefaultTests.cs index 421f9685470a4f..55d93850330328 100644 --- a/src/libraries/System.Linq/tests/ElementAtOrDefaultTests.cs +++ b/src/libraries/System.Linq/tests/ElementAtOrDefaultTests.cs @@ -11,39 +11,23 @@ public class ElementAtOrDefaultTests : EnumerableTests [Fact] public void SameResultsRepeatCallsIntQuery() { - var q1 = from x in new[] { 9999, 0, 888, -1, 66, -777, 1, 2, -12345 } - where x > int.MinValue - select x; - Assert.Equal(q1.ElementAtOrDefault(3), q1.ElementAtOrDefault(3)); - - var q2 = from x in new[] { 9999, 0, 888, -1, 66, -777, 1, 2, -12345 } - where x > int.MinValue - select x; - Assert.Equal(q2.ElementAtOrDefault(new Index(3)), q2.ElementAtOrDefault(new Index(3))); - - var q3 = from x in new[] { 9999, 0, 888, -1, 66, -777, 1, 2, -12345 } + var q = Repeat(_ => from x in new[] { 9999, 0, 888, -1, 66, -777, 1, 2, -12345 } where x > int.MinValue - select x; - Assert.Equal(q3.ElementAtOrDefault(^6), q3.ElementAtOrDefault(^6)); + 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 q1 = from x in new[] { "!@#$%^", "C", "AAA", "", "Calling Twice", "SoS", string.Empty } - where !string.IsNullOrEmpty(x) - select x; - Assert.Equal(q1.ElementAtOrDefault(4), q1.ElementAtOrDefault(4)); - - var q2 = from x in new[] { "!@#$%^", "C", "AAA", "", "Calling Twice", "SoS", string.Empty } - where !string.IsNullOrEmpty(x) - select x; - Assert.Equal(q2.ElementAtOrDefault(new Index(4)), q2.ElementAtOrDefault(new Index(4))); - - var q3 = from x in new[] { "!@#$%^", "C", "AAA", "", "Calling Twice", "SoS", string.Empty } + var q = Repeat(_ => from x in new[] { "!@#$%^", "C", "AAA", "", "Calling Twice", "SoS", string.Empty } where !string.IsNullOrEmpty(x) - select x; - Assert.Equal(q3.ElementAtOrDefault(^2), q3.ElementAtOrDefault(^2)); + 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() diff --git a/src/libraries/System.Linq/tests/ElementAtTests.cs b/src/libraries/System.Linq/tests/ElementAtTests.cs index 56438725438c19..8c3e2ffb32d3cd 100644 --- a/src/libraries/System.Linq/tests/ElementAtTests.cs +++ b/src/libraries/System.Linq/tests/ElementAtTests.cs @@ -11,39 +11,23 @@ public class ElementAtTests : EnumerableTests [Fact] public void SameResultsRepeatCallsIntQuery() { - var q1 = from x in new[] { 9999, 0, 888, -1, 66, -777, 1, 2, -12345 } - where x > int.MinValue - select x; - Assert.Equal(q1.ElementAt(3), q1.ElementAt(3)); - - var q2 = from x in new[] { 9999, 0, 888, -1, 66, -777, 1, 2, -12345 } - where x > int.MinValue - select x; - Assert.Equal(q2.ElementAt(new Index(3)), q2.ElementAt(new Index(3))); - - var q3 = from x in new[] { 9999, 0, 888, -1, 66, -777, 1, 2, -12345 } + var q = Repeat(_ => from x in new[] { 9999, 0, 888, -1, 66, -777, 1, 2, -12345 } where x > int.MinValue - select x; - Assert.Equal(q3.ElementAt(^6), q3.ElementAt(^6)); + 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 q1 = from x in new[] { "!@#$%^", "C", "AAA", "", "Calling Twice", "SoS", string.Empty } - where !string.IsNullOrEmpty(x) - select x; - Assert.Equal(q1.ElementAt(4), q1.ElementAt(4)); - - var q2 = from x in new[] { "!@#$%^", "C", "AAA", "", "Calling Twice", "SoS", string.Empty } - where !string.IsNullOrEmpty(x) - select x; - Assert.Equal(q2.ElementAt(new Index(4)), q2.ElementAt(new Index(4))); - - var q3 = from x in new[] { "!@#$%^", "C", "AAA", "", "Calling Twice", "SoS", string.Empty } + var q = Repeat(_ => from x in new[] { "!@#$%^", "C", "AAA", "", "Calling Twice", "SoS", string.Empty } where !string.IsNullOrEmpty(x) - select x; - Assert.Equal(q3.ElementAt(^2), q3.ElementAt(^2)); + 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() diff --git a/src/libraries/System.Linq/tests/EnumerableTests.cs b/src/libraries/System.Linq/tests/EnumerableTests.cs index 1bb71e61df008b..f5a865fe5b18db 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,30 @@ 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 ListPartition(IList source) + { + var listPartition = source.Skip(0); // new ListPartition(sourceList, count, int.MaxValue) + Assert.True(listPartition.GetType().Name.Contains(nameof(ListPartition), StringComparison.InvariantCulture)); + return listPartition; + } + + protected static IEnumerable EnumerablePartition(IEnumerable source) + { + var enumerablePartition = ForceNotCollection(source).Skip(0); // new EnumerablePartition(source, count, -1) + Assert.True(enumerablePartition.GetType().Name.Contains(nameof(EnumerablePartition), StringComparison.InvariantCulture)); + return enumerablePartition; + } protected struct StringWithIntArray { diff --git a/src/libraries/System.Linq/tests/TakeTests.cs b/src/libraries/System.Linq/tests/TakeTests.cs index b5331edce351e3..24b9c0666165c6 100644 --- a/src/libraries/System.Linq/tests/TakeTests.cs +++ b/src/libraries/System.Linq/tests/TakeTests.cs @@ -8,39 +8,13 @@ namespace System.Linq.Tests { public class TakeTests : EnumerableTests { - private static IEnumerable GuaranteeNotIList(IEnumerable source) - { - foreach (T element in source) - yield return element; - } - - private static T[] Repeat(Func factory, int count = 5) - { - T[] results = new T[count]; - for (int index = 0; index < results.Length; index++) - { - results[index] = factory(index); - } - - return results; - } - - private static IEnumerable ToListPartition(IList source) - { - return source.Skip(0); - } - - private static IEnumerable ToEnumerablePartition(IList source) - { - return GuaranteeNotIList(source).Skip(0); - } [Fact] public void SameResultsRepeatCallsIntQuery() { var q = Repeat(_ => from x in new[] { 9999, 0, 888, -1, 66, -777, 1, 2, -12345 } where x > int.MinValue - select x); + select x, 5); Assert.Equal(q[0].Take(9), q[0].Take(9)); @@ -48,11 +22,6 @@ where x > int.MinValue Assert.Equal(q[2].Take(^9..9), q[2].Take(^9..9)); Assert.Equal(q[3].Take(0..^0), q[3].Take(0..^0)); Assert.Equal(q[4].Take(^9..^0), q[4].Take(^9..^0)); - //Assert.Equal(q[5].Take(..9), q[5].Take(..9)); - //Assert.Equal(q[6].Take(..^0), q[6].Take(..^0)); - //Assert.Equal(q[7].Take(0..), q[7].Take(0..)); - //Assert.Equal(q[8].Take(..), q[8].Take(..)); - //Assert.Equal(q[9].Take(^9..), q[9].Take(^9..)); } [Fact] @@ -60,7 +29,7 @@ public void SameResultsRepeatCallsIntQueryIList() { var q = Repeat(_ => (from x in new[] { 9999, 0, 888, -1, 66, -777, 1, 2, -12345 } where x > Int32.MinValue - select x).ToList()); + select x).ToList(), 5); Assert.Equal(q[0].Take(9), q[0].Take(9)); @@ -68,11 +37,6 @@ where x > Int32.MinValue Assert.Equal(q[2].Take(^9..9), q[2].Take(^9..9)); Assert.Equal(q[3].Take(0..^0), q[3].Take(0..^0)); Assert.Equal(q[4].Take(^9..^0), q[4].Take(^9..^0)); - //Assert.Equal(q[5].Take(..9), q[5].Take(..9)); - //Assert.Equal(q[6].Take(..^0), q[6].Take(..^0)); - //Assert.Equal(q[7].Take(0..), q[7].Take(0..)); - //Assert.Equal(q[8].Take(..), q[8].Take(..)); - //Assert.Equal(q[9].Take(^9..), q[9].Take(^9..)); } [Fact] @@ -80,7 +44,7 @@ public void SameResultsRepeatCallsStringQuery() { var q = Repeat(_ => from x in new[] { "!@#$%^", "C", "AAA", "", "Calling Twice", "SoS", string.Empty } where !string.IsNullOrEmpty(x) - select x); + select x, 5); Assert.Equal(q[0].Take(7), q[0].Take(7)); @@ -95,7 +59,7 @@ public void SameResultsRepeatCallsStringQueryIList() { var q = Repeat(_ => (from x in new[] { "!@#$%^", "C", "AAA", "", "Calling Twice", "SoS", String.Empty } where !String.IsNullOrEmpty(x) - select x).ToList()); + select x).ToList(), 5); Assert.Equal(q[0].Take(7), q[0].Take(7)); @@ -141,7 +105,7 @@ public void SourceNonEmptyCountNegative() [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)); @@ -162,7 +126,7 @@ public void SourceNonEmptyCountZero() [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)); @@ -188,7 +152,7 @@ public void SourceNonEmptyCountOne() [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)); @@ -215,7 +179,7 @@ public void SourceNonEmptyTakeAllExactly() [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())); @@ -256,7 +220,7 @@ public void RunOnce() [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)); @@ -281,7 +245,7 @@ public void SourceNonEmptyTakeExcessive() [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)); @@ -348,7 +312,6 @@ public void ForcedToEnumeratorDoesntEnumerateIList() Assert.False(en1 != null && en1.MoveNext()); var iterator2 = NumberRangeGuaranteedNotCollectionType(0, 3).ToList().Take(2); - // Don't insist on this behaviour, but check it's correct if it happens var en2 = iterator2 as IEnumerator; Assert.False(en2 != null && en2.MoveNext()); } @@ -421,29 +384,29 @@ public void ElementAt() AssertExtensions.Throws("index", () => taken2.ElementAt(-1)); AssertExtensions.Throws("index", () => taken2.ElementAt(3)); - taken2 = source.Take(^6..3); - Assert.Equal(1, taken2.ElementAt(0)); - Assert.Equal(3, taken2.ElementAt(2)); - AssertExtensions.Throws("index", () => taken2.ElementAt(-1)); - AssertExtensions.Throws("index", () => taken2.ElementAt(3)); + var taken3 = source.Take(^6..3); + Assert.Equal(1, taken3.ElementAt(0)); + Assert.Equal(3, taken3.ElementAt(2)); + AssertExtensions.Throws("index", () => taken3.ElementAt(-1)); + AssertExtensions.Throws("index", () => taken3.ElementAt(3)); - taken2 = source.Take(0..^3); - Assert.Equal(1, taken2.ElementAt(0)); - Assert.Equal(3, taken2.ElementAt(2)); - AssertExtensions.Throws("index", () => taken2.ElementAt(-1)); - AssertExtensions.Throws("index", () => taken2.ElementAt(3)); + var taken4 = source.Take(0..^3); + Assert.Equal(1, taken4.ElementAt(0)); + Assert.Equal(3, taken4.ElementAt(2)); + AssertExtensions.Throws("index", () => taken4.ElementAt(-1)); + AssertExtensions.Throws("index", () => taken4.ElementAt(3)); - taken2 = source.Take(^6..^3); - Assert.Equal(1, taken2.ElementAt(0)); - Assert.Equal(3, taken2.ElementAt(2)); - AssertExtensions.Throws("index", () => taken2.ElementAt(-1)); - AssertExtensions.Throws("index", () => taken2.ElementAt(3)); + var taken5 = source.Take(^6..^3); + Assert.Equal(1, taken5.ElementAt(0)); + Assert.Equal(3, taken5.ElementAt(2)); + AssertExtensions.Throws("index", () => taken5.ElementAt(-1)); + AssertExtensions.Throws("index", () => taken5.ElementAt(3)); } [Fact] public void ElementAtNotIList() { - var source = GuaranteeNotIList(new[] { 1, 2, 3, 4, 5, 6 }); + var source = ForceNotCollection(new[] { 1, 2, 3, 4, 5, 6 }); var taken1 = source.Take(3); Assert.Equal(1, taken1.ElementAt(0)); Assert.Equal(3, taken1.ElementAt(2)); @@ -456,23 +419,23 @@ public void ElementAtNotIList() AssertExtensions.Throws("index", () => taken2.ElementAt(-1)); AssertExtensions.Throws("index", () => taken2.ElementAt(3)); - taken2 = source.Take(^6..3); - Assert.Equal(1, taken2.ElementAt(0)); - Assert.Equal(3, taken2.ElementAt(2)); - AssertExtensions.Throws("index", () => taken2.ElementAt(-1)); - AssertExtensions.Throws("index", () => taken2.ElementAt(3)); + var taken3 = source.Take(^6..3); + Assert.Equal(1, taken3.ElementAt(0)); + Assert.Equal(3, taken3.ElementAt(2)); + AssertExtensions.Throws("index", () => taken3.ElementAt(-1)); + AssertExtensions.Throws("index", () => taken3.ElementAt(3)); - taken2 = source.Take(0..^3); - Assert.Equal(1, taken2.ElementAt(0)); - Assert.Equal(3, taken2.ElementAt(2)); - AssertExtensions.Throws("index", () => taken2.ElementAt(-1)); - AssertExtensions.Throws("index", () => taken2.ElementAt(3)); + var taken4 = source.Take(0..^3); + Assert.Equal(1, taken4.ElementAt(0)); + Assert.Equal(3, taken4.ElementAt(2)); + AssertExtensions.Throws("index", () => taken4.ElementAt(-1)); + AssertExtensions.Throws("index", () => taken4.ElementAt(3)); - taken2 = source.Take(^6..^3); - Assert.Equal(1, taken2.ElementAt(0)); - Assert.Equal(3, taken2.ElementAt(2)); - AssertExtensions.Throws("index", () => taken2.ElementAt(-1)); - AssertExtensions.Throws("index", () => taken2.ElementAt(3)); + var taken5 = source.Take(^6..^3); + Assert.Equal(1, taken5.ElementAt(0)); + Assert.Equal(3, taken5.ElementAt(2)); + AssertExtensions.Throws("index", () => taken5.ElementAt(-1)); + AssertExtensions.Throws("index", () => taken5.ElementAt(3)); } [Fact] @@ -491,29 +454,29 @@ public void ElementAtOrDefault() Assert.Equal(0, taken2.ElementAtOrDefault(-1)); Assert.Equal(0, taken2.ElementAtOrDefault(3)); - 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(^6..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)); - taken2 = source.Take(0..^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 taken4 = source.Take(0..^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)); - 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 taken5 = source.Take(^6..^3); + Assert.Equal(1, taken5.ElementAtOrDefault(0)); + Assert.Equal(3, taken5.ElementAtOrDefault(2)); + Assert.Equal(0, taken5.ElementAtOrDefault(-1)); + Assert.Equal(0, taken5.ElementAtOrDefault(3)); } [Fact] public void ElementAtOrDefaultNotIList() { - var source = GuaranteeNotIList(new[] { 1, 2, 3, 4, 5, 6 }); + var source = ForceNotCollection(new[] { 1, 2, 3, 4, 5, 6 }); var taken1 = source.Take(3); Assert.Equal(1, taken1.ElementAtOrDefault(0)); Assert.Equal(3, taken1.ElementAtOrDefault(2)); @@ -526,23 +489,23 @@ public void ElementAtOrDefaultNotIList() Assert.Equal(0, taken2.ElementAtOrDefault(-1)); Assert.Equal(0, taken2.ElementAtOrDefault(3)); - 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(^6..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)); - taken2 = source.Take(0..^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 taken4 = source.Take(0..^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)); - 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 taken5 = source.Take(^6..^3); + Assert.Equal(1, taken5.ElementAtOrDefault(0)); + Assert.Equal(3, taken5.ElementAtOrDefault(2)); + Assert.Equal(0, taken5.ElementAtOrDefault(-1)); + Assert.Equal(0, taken5.ElementAtOrDefault(3)); } [Fact] @@ -577,7 +540,7 @@ public void 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()); @@ -641,7 +604,7 @@ public void 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()); @@ -711,36 +674,36 @@ public void 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(() => GuaranteeNotIList(Array.Empty()).Take(0..40).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(() => GuaranteeNotIList(Array.Empty()).Take(^5..40).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(() => GuaranteeNotIList(Array.Empty()).Take(0..^0).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(() => GuaranteeNotIList(Array.Empty()).Take(^40..^0).Last()); + Assert.Throws(() => ForceNotCollection(Array.Empty()).Take(^40..^0).Last()); } [Fact] @@ -781,36 +744,36 @@ public void 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, GuaranteeNotIList(Array.Empty()).Take(0..40).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, GuaranteeNotIList(Array.Empty()).Take(^5..40).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, GuaranteeNotIList(Array.Empty()).Take(0..^0).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, GuaranteeNotIList(Array.Empty()).Take(^40..^0).LastOrDefault()); + Assert.Equal(0, ForceNotCollection(Array.Empty()).Take(^40..^0).LastOrDefault()); } [Fact] @@ -858,7 +821,7 @@ public void 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()); @@ -942,7 +905,7 @@ public void 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()); @@ -1014,7 +977,7 @@ public void TakeCanOnlyBeOneList() [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)); @@ -1051,34 +1014,34 @@ public void RepeatEnumerating() var taken2 = source.Take(0..3); Assert.Equal(taken2, taken2); - taken2 = source.Take(^5..3); - Assert.Equal(taken2, taken2); + var taken3 = source.Take(^5..3); + Assert.Equal(taken3, taken3); - taken2 = source.Take(0..^2); - Assert.Equal(taken2, taken2); + var taken4 = source.Take(0..^2); + Assert.Equal(taken4, taken4); - taken2 = source.Take(^5..^2); - Assert.Equal(taken2, taken2); + var taken5 = source.Take(^5..^2); + Assert.Equal(taken5, taken5); } [Fact] public void RepeatEnumeratingNotList() { - var source = GuaranteeNotIList(new[] { 1, 2, 3, 4, 5 }); + 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); - taken2 = source.Take(^5..3); - Assert.Equal(taken2, taken2); + var taken3 = source.Take(^5..3); + Assert.Equal(taken3, taken3); - taken2 = source.Take(0..^2); - Assert.Equal(taken2, taken2); + var taken4 = source.Take(0..^2); + Assert.Equal(taken4, taken4); - taken2 = source.Take(^5..^2); - Assert.Equal(taken2, taken2); + var taken5 = source.Take(^5..^2); + Assert.Equal(taken5, taken5); } [Theory] @@ -1109,28 +1072,28 @@ public void LazyOverflowRegression() Assert.Equal(Enumerable.Range(43, 100 - 42), taken1.ToList()); var taken2 = NumberRangeGuaranteedNotCollectionType(1, 100).Skip(42).Take(0..int.MaxValue); - 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()); - - taken2 = NumberRangeGuaranteedNotCollectionType(1, 100).Skip(42).Take(^int.MaxValue..int.MaxValue); - 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()); - - taken2 = NumberRangeGuaranteedNotCollectionType(1, 100).Skip(42).Take(int.MaxValue..^0); - 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()); - - taken2 = NumberRangeGuaranteedNotCollectionType(1, 100).Skip(42).Take(^int.MaxValue..^0); - 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()); + 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).Skip(42).Take(^int.MaxValue..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).Skip(42).Take(int.MaxValue..^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).Skip(42).Take(^int.MaxValue..^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] @@ -1167,20 +1130,20 @@ public void CountOfLazySkipTakeChain(int skip, int take, int expected) Assert.Equal(expected, partition2.Select(i => i).Count()); Assert.Equal(expected, partition2.Select(i => i).ToArray().Length); - partition2 = NumberRangeGuaranteedNotCollectionType(1, totalCount).Take(^Math.Max(totalCount - skip, 0)..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); - partition2 = NumberRangeGuaranteedNotCollectionType(1, totalCount).Take(skip..^Math.Max(totalCount - end, 0)); - Assert.Equal(expected, partition2.Count()); - Assert.Equal(expected, partition2.Select(i => i).Count()); - Assert.Equal(expected, partition2.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); - partition2 = NumberRangeGuaranteedNotCollectionType(1, totalCount).Take(^Math.Max(totalCount - skip, 0)..^Math.Max(totalCount - end, 0)); - Assert.Equal(expected, partition2.Count()); - Assert.Equal(expected, partition2.Select(i => i).Count()); - Assert.Equal(expected, partition2.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] @@ -1216,26 +1179,26 @@ public void FirstAndLastOfLazySkipTakeChain(int[] source, int skip, int take, in Assert.Equal(last, partition2.LastOrDefault()); Assert.Equal(last, partition2.ElementAtOrDefault(partition2.Count() - 1)); - partition2 = ForceNotCollection(source).Take(^Math.Max(source.Length - skip, 0)..end); + var partition3 = ForceNotCollection(source).Take(^Math.Max(source.Length - skip, 0)..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)); + Assert.Equal(first, partition3.FirstOrDefault()); + Assert.Equal(first, partition3.ElementAtOrDefault(0)); + Assert.Equal(last, partition3.LastOrDefault()); + Assert.Equal(last, partition3.ElementAtOrDefault(partition3.Count() - 1)); - partition2 = ForceNotCollection(source).Take(skip..^Math.Max(source.Length - end, 0)); + var partition4 = ForceNotCollection(source).Take(skip..^Math.Max(source.Length - end, 0)); - Assert.Equal(first, partition2.FirstOrDefault()); - Assert.Equal(first, partition2.ElementAtOrDefault(0)); - Assert.Equal(last, partition2.LastOrDefault()); - Assert.Equal(last, partition2.ElementAtOrDefault(partition2.Count() - 1)); + Assert.Equal(first, partition4.FirstOrDefault()); + Assert.Equal(first, partition4.ElementAtOrDefault(0)); + Assert.Equal(last, partition4.LastOrDefault()); + Assert.Equal(last, partition4.ElementAtOrDefault(partition4.Count() - 1)); - partition2 = ForceNotCollection(source).Take(^Math.Max(source.Length - skip, 0)..^Math.Max(source.Length - end, 0)); + var partition5 = ForceNotCollection(source).Take(^Math.Max(source.Length - skip, 0)..^Math.Max(source.Length - end, 0)); - Assert.Equal(first, partition2.FirstOrDefault()); - Assert.Equal(first, partition2.ElementAtOrDefault(0)); - Assert.Equal(last, partition2.LastOrDefault()); - Assert.Equal(last, partition2.ElementAtOrDefault(partition2.Count() - 1)); + 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] @@ -1302,7 +1265,7 @@ public void DisposeSource(int sourceCount, int count) var source = Repeat(index => new DelegateIterator( moveNext: () => ++state[index] <= sourceCount, current: () => 0, - dispose: () => state[index] = -1)); + dispose: () => state[index] = -1), 5); IEnumerator iterator0 = source[0].Take(count).GetEnumerator(); int iteratorCount0 = Math.Min(sourceCount, Math.Max(0, count)); @@ -1381,36 +1344,36 @@ public void OutOfBoundNoExceptionNotList() { var source = new[] { 1, 2, 3, 4, 5 }; - Assert.Equal(source, GuaranteeNotIList(source).Take(0..6)); - Assert.Equal(source, GuaranteeNotIList(source).Take(0..int.MaxValue)); - - Assert.Equal(new int[] { 1, 2, 3, 4 }, GuaranteeNotIList(source).Take(^10..4)); - Assert.Equal(new int[] { 1, 2, 3, 4 }, GuaranteeNotIList(source).Take(^int.MaxValue..4)); - Assert.Equal(source, GuaranteeNotIList(source).Take(^10..6)); - Assert.Equal(source, GuaranteeNotIList(source).Take(^int.MaxValue..6)); - Assert.Equal(source, GuaranteeNotIList(source).Take(^10..int.MaxValue)); - Assert.Equal(source, GuaranteeNotIList(source).Take(^int.MaxValue..int.MaxValue)); - - Assert.Empty(GuaranteeNotIList(source).Take(0..^6)); - Assert.Empty(GuaranteeNotIList(source).Take(0..^int.MaxValue)); - Assert.Empty(GuaranteeNotIList(source).Take(4..^6)); - Assert.Empty(GuaranteeNotIList(source).Take(4..^int.MaxValue)); - Assert.Empty(GuaranteeNotIList(source).Take(6..^6)); - Assert.Empty(GuaranteeNotIList(source).Take(6..^int.MaxValue)); - Assert.Empty(GuaranteeNotIList(source).Take(int.MaxValue..^6)); - Assert.Empty(GuaranteeNotIList(source).Take(int.MaxValue..^int.MaxValue)); - - Assert.Equal(new int[] { 1, 2, 3, 4 }, GuaranteeNotIList(source).Take(^10..^1)); - Assert.Equal(new int[] { 1, 2, 3, 4 }, GuaranteeNotIList(source).Take(^int.MaxValue..^1)); - Assert.Empty(GuaranteeNotIList(source).Take(^0..^6)); - Assert.Empty(GuaranteeNotIList(source).Take(^1..^6)); - Assert.Empty(GuaranteeNotIList(source).Take(^6..^6)); - Assert.Empty(GuaranteeNotIList(source).Take(^10..^6)); - Assert.Empty(GuaranteeNotIList(source).Take(^int.MaxValue..^6)); - Assert.Empty(GuaranteeNotIList(source).Take(^0..^int.MaxValue)); - Assert.Empty(GuaranteeNotIList(source).Take(^1..^int.MaxValue)); - Assert.Empty(GuaranteeNotIList(source).Take(^6..^int.MaxValue)); - Assert.Empty(GuaranteeNotIList(source).Take(^int.MaxValue..^int.MaxValue)); + 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] @@ -1435,7 +1398,7 @@ public void MutableSource() Assert.Equal(new[] { 1, 2, -1 }, query3); var source4 = new List() { 0, 1, 2, 3, 4 }; - var query4 = source4.Take(^6..3); + var query4 = source4.Take(^6..^3); source4.RemoveAt(0); source4.InsertRange(2, new[] { -1, -2 }); Assert.Equal(new[] { 1, 2, -1 }, query4); @@ -1445,25 +1408,25 @@ public void MutableSource() public void MutableSourceNotList() { var source1 = new List() { 0, 1, 2, 3, 4 }; - var query1 = GuaranteeNotIList(source1).Select(i => i).Take(3); + 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 = GuaranteeNotIList(source1).Select(i => i).Take(0..3); + 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 = GuaranteeNotIList(source1).Select(i => i).Take(^6..3); + 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 = GuaranteeNotIList(source1).Select(i => i).Take(^6..3); + 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); @@ -1521,44 +1484,44 @@ public void NonEmptySource_ConsistentWithCountable_NotList() int[] source = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; // Multiple elements in the middle. - Assert.Equal(source[^9..5], GuaranteeNotIList(source).Take(^9..5)); - Assert.Equal(source[2..7], GuaranteeNotIList(source).Take(2..7)); - Assert.Equal(source[2..^4], GuaranteeNotIList(source).Take(2..^4)); - Assert.Equal(source[^7..^4], GuaranteeNotIList(source).Take(^7..^4)); + 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..], GuaranteeNotIList(source).Take(^9..)); - Assert.Equal(source[2..], GuaranteeNotIList(source).Take(2..)); - Assert.Equal(source[..^4], GuaranteeNotIList(source).Take(..^4)); - Assert.Equal(source[..6], GuaranteeNotIList(source).Take(..6)); + 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[..], GuaranteeNotIList(source).Take(..)); + Assert.Equal(source[..], ForceNotCollection(source).Take(..)); // Single element in the middle. - Assert.Equal(source[^9..2], GuaranteeNotIList(source).Take(^9..2)); - Assert.Equal(source[2..3], GuaranteeNotIList(source).Take(2..3)); - Assert.Equal(source[2..^7], GuaranteeNotIList(source).Take(2..^7)); - Assert.Equal(source[^5..^4], GuaranteeNotIList(source).Take(^5..^4)); + 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], GuaranteeNotIList(source).Take(^10..1)); - Assert.Equal(source[0..1], GuaranteeNotIList(source).Take(0..1)); - Assert.Equal(source[0..^9], GuaranteeNotIList(source).Take(0..^9)); - Assert.Equal(source[^10..^9], GuaranteeNotIList(source).Take(^10..^9)); + 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], GuaranteeNotIList(source).Take(^1..10)); - Assert.Equal(source[9..10], GuaranteeNotIList(source).Take(9..10)); - Assert.Equal(source[9..^0], GuaranteeNotIList(source).Take(9..^0)); - Assert.Equal(source[^1..^0], GuaranteeNotIList(source).Take(^1..^0)); + 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], GuaranteeNotIList(source).Take(3..3)); - Assert.Equal(source[6..^4], GuaranteeNotIList(source).Take(6..^4)); - Assert.Equal(source[3..^7], GuaranteeNotIList(source).Take(3..^7)); - Assert.Equal(source[^3..7], GuaranteeNotIList(source).Take(^3..7)); - Assert.Equal(source[^6..^6], GuaranteeNotIList(source).Take(^6..^6)); + 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] @@ -1567,44 +1530,44 @@ public void NonEmptySource_ConsistentWithCountable_ListPartition() int[] source = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; // Multiple elements in the middle. - Assert.Equal(source[^9..5], ToListPartition(source).Take(^9..5)); - Assert.Equal(source[2..7], ToListPartition(source).Take(2..7)); - Assert.Equal(source[2..^4], ToListPartition(source).Take(2..^4)); - Assert.Equal(source[^7..^4], ToListPartition(source).Take(^7..^4)); + Assert.Equal(source[^9..5], ListPartition(source).Take(^9..5)); + Assert.Equal(source[2..7], ListPartition(source).Take(2..7)); + Assert.Equal(source[2..^4], ListPartition(source).Take(2..^4)); + Assert.Equal(source[^7..^4], ListPartition(source).Take(^7..^4)); // Range with default index. - Assert.Equal(source[^9..], ToListPartition(source).Take(^9..)); - Assert.Equal(source[2..], ToListPartition(source).Take(2..)); - Assert.Equal(source[..^4], ToListPartition(source).Take(..^4)); - Assert.Equal(source[..6], ToListPartition(source).Take(..6)); + Assert.Equal(source[^9..], ListPartition(source).Take(^9..)); + Assert.Equal(source[2..], ListPartition(source).Take(2..)); + Assert.Equal(source[..^4], ListPartition(source).Take(..^4)); + Assert.Equal(source[..6], ListPartition(source).Take(..6)); // All. - Assert.Equal(source[..], ToListPartition(source).Take(..)); + Assert.Equal(source[..], ListPartition(source).Take(..)); // Single element in the middle. - Assert.Equal(source[^9..2], ToListPartition(source).Take(^9..2)); - Assert.Equal(source[2..3], ToListPartition(source).Take(2..3)); - Assert.Equal(source[2..^7], ToListPartition(source).Take(2..^7)); - Assert.Equal(source[^5..^4], ToListPartition(source).Take(^5..^4)); + Assert.Equal(source[^9..2], ListPartition(source).Take(^9..2)); + Assert.Equal(source[2..3], ListPartition(source).Take(2..3)); + Assert.Equal(source[2..^7], ListPartition(source).Take(2..^7)); + Assert.Equal(source[^5..^4], ListPartition(source).Take(^5..^4)); // Single element at start. - Assert.Equal(source[^10..1], ToListPartition(source).Take(^10..1)); - Assert.Equal(source[0..1], ToListPartition(source).Take(0..1)); - Assert.Equal(source[0..^9], ToListPartition(source).Take(0..^9)); - Assert.Equal(source[^10..^9], ToListPartition(source).Take(^10..^9)); + Assert.Equal(source[^10..1], ListPartition(source).Take(^10..1)); + Assert.Equal(source[0..1], ListPartition(source).Take(0..1)); + Assert.Equal(source[0..^9], ListPartition(source).Take(0..^9)); + Assert.Equal(source[^10..^9], ListPartition(source).Take(^10..^9)); // Single element at end. - Assert.Equal(source[^1..10], ToListPartition(source).Take(^1..10)); - Assert.Equal(source[9..10], ToListPartition(source).Take(9..10)); - Assert.Equal(source[9..^0], ToListPartition(source).Take(9..^0)); - Assert.Equal(source[^1..^0], ToListPartition(source).Take(^1..^0)); + Assert.Equal(source[^1..10], ListPartition(source).Take(^1..10)); + Assert.Equal(source[9..10], ListPartition(source).Take(9..10)); + Assert.Equal(source[9..^0], ListPartition(source).Take(9..^0)); + Assert.Equal(source[^1..^0], ListPartition(source).Take(^1..^0)); // No element. - Assert.Equal(source[3..3], ToListPartition(source).Take(3..3)); - Assert.Equal(source[6..^4], ToListPartition(source).Take(6..^4)); - Assert.Equal(source[3..^7], ToListPartition(source).Take(3..^7)); - Assert.Equal(source[^3..7], ToListPartition(source).Take(^3..7)); - Assert.Equal(source[^6..^6], ToListPartition(source).Take(^6..^6)); + Assert.Equal(source[3..3], ListPartition(source).Take(3..3)); + Assert.Equal(source[6..^4], ListPartition(source).Take(6..^4)); + Assert.Equal(source[3..^7], ListPartition(source).Take(3..^7)); + Assert.Equal(source[^3..7], ListPartition(source).Take(^3..7)); + Assert.Equal(source[^6..^6], ListPartition(source).Take(^6..^6)); } [Fact] @@ -1613,44 +1576,44 @@ public void NonEmptySource_ConsistentWithCountable_EnumerablePartition() int[] source = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; // Multiple elements in the middle. - Assert.Equal(source[^9..5], ToEnumerablePartition(source).Take(^9..5)); - Assert.Equal(source[2..7], ToEnumerablePartition(source).Take(2..7)); - Assert.Equal(source[2..^4], ToEnumerablePartition(source).Take(2..^4)); - Assert.Equal(source[^7..^4], ToEnumerablePartition(source).Take(^7..^4)); + Assert.Equal(source[^9..5], EnumerablePartition(source).Take(^9..5)); + Assert.Equal(source[2..7], EnumerablePartition(source).Take(2..7)); + Assert.Equal(source[2..^4], EnumerablePartition(source).Take(2..^4)); + Assert.Equal(source[^7..^4], EnumerablePartition(source).Take(^7..^4)); // Range with default index. - Assert.Equal(source[^9..], ToEnumerablePartition(source).Take(^9..)); - Assert.Equal(source[2..], ToEnumerablePartition(source).Take(2..)); - Assert.Equal(source[..^4], ToEnumerablePartition(source).Take(..^4)); - Assert.Equal(source[..6], ToEnumerablePartition(source).Take(..6)); + Assert.Equal(source[^9..], EnumerablePartition(source).Take(^9..)); + Assert.Equal(source[2..], EnumerablePartition(source).Take(2..)); + Assert.Equal(source[..^4], EnumerablePartition(source).Take(..^4)); + Assert.Equal(source[..6], EnumerablePartition(source).Take(..6)); // All. - Assert.Equal(source[..], ToEnumerablePartition(source).Take(..)); + Assert.Equal(source[..], EnumerablePartition(source).Take(..)); // Single element in the middle. - Assert.Equal(source[^9..2], ToEnumerablePartition(source).Take(^9..2)); - Assert.Equal(source[2..3], ToEnumerablePartition(source).Take(2..3)); - Assert.Equal(source[2..^7], ToEnumerablePartition(source).Take(2..^7)); - Assert.Equal(source[^5..^4], ToEnumerablePartition(source).Take(^5..^4)); + Assert.Equal(source[^9..2], EnumerablePartition(source).Take(^9..2)); + Assert.Equal(source[2..3], EnumerablePartition(source).Take(2..3)); + Assert.Equal(source[2..^7], EnumerablePartition(source).Take(2..^7)); + Assert.Equal(source[^5..^4], EnumerablePartition(source).Take(^5..^4)); // Single element at start. - Assert.Equal(source[^10..1], ToEnumerablePartition(source).Take(^10..1)); - Assert.Equal(source[0..1], ToEnumerablePartition(source).Take(0..1)); - Assert.Equal(source[0..^9], ToEnumerablePartition(source).Take(0..^9)); - Assert.Equal(source[^10..^9], ToEnumerablePartition(source).Take(^10..^9)); + Assert.Equal(source[^10..1], EnumerablePartition(source).Take(^10..1)); + Assert.Equal(source[0..1], EnumerablePartition(source).Take(0..1)); + Assert.Equal(source[0..^9], EnumerablePartition(source).Take(0..^9)); + Assert.Equal(source[^10..^9], EnumerablePartition(source).Take(^10..^9)); // Single element at end. - Assert.Equal(source[^1..10], ToEnumerablePartition(source).Take(^1..10)); - Assert.Equal(source[9..10], ToEnumerablePartition(source).Take(9..10)); - Assert.Equal(source[9..^0], ToEnumerablePartition(source).Take(9..^0)); - Assert.Equal(source[^1..^0], ToEnumerablePartition(source).Take(^1..^0)); + Assert.Equal(source[^1..10], EnumerablePartition(source).Take(^1..10)); + Assert.Equal(source[9..10], EnumerablePartition(source).Take(9..10)); + Assert.Equal(source[9..^0], EnumerablePartition(source).Take(9..^0)); + Assert.Equal(source[^1..^0], EnumerablePartition(source).Take(^1..^0)); // No element. - Assert.Equal(source[3..3], ToEnumerablePartition(source).Take(3..3)); - Assert.Equal(source[6..^4], ToEnumerablePartition(source).Take(6..^4)); - Assert.Equal(source[3..^7], ToEnumerablePartition(source).Take(3..^7)); - Assert.Equal(source[^3..7], ToEnumerablePartition(source).Take(^3..7)); - Assert.Equal(source[^6..^6], ToEnumerablePartition(source).Take(^6..^6)); + Assert.Equal(source[3..3], EnumerablePartition(source).Take(3..3)); + Assert.Equal(source[6..^4], EnumerablePartition(source).Take(6..^4)); + Assert.Equal(source[3..^7], EnumerablePartition(source).Take(3..^7)); + Assert.Equal(source[^3..7], EnumerablePartition(source).Take(^3..7)); + Assert.Equal(source[^6..^6], EnumerablePartition(source).Take(^6..^6)); } [Fact] @@ -1669,10 +1632,10 @@ public void NonEmptySource_DoNotThrowException_NotList() { int[] source = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; - Assert.Empty(GuaranteeNotIList(source).Take(3..2)); - Assert.Empty(GuaranteeNotIList(source).Take(6..^5)); - Assert.Empty(GuaranteeNotIList(source).Take(3..^8)); - Assert.Empty(GuaranteeNotIList(source).Take(^6..^7)); + 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] @@ -1680,10 +1643,10 @@ public void NonEmptySource_DoNotThrowException_ListPartition() { int[] source = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; - Assert.Empty(ToListPartition(source).Take(3..2)); - Assert.Empty(ToListPartition(source).Take(6..^5)); - Assert.Empty(ToListPartition(source).Take(3..^8)); - Assert.Empty(ToListPartition(source).Take(^6..^7)); + Assert.Empty(ListPartition(source).Take(3..2)); + Assert.Empty(ListPartition(source).Take(6..^5)); + Assert.Empty(ListPartition(source).Take(3..^8)); + Assert.Empty(ListPartition(source).Take(^6..^7)); } [Fact] @@ -1691,10 +1654,10 @@ public void NonEmptySource_DoNotThrowException_EnumerablePartition() { int[] source = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; - Assert.Empty(ToEnumerablePartition(source).Take(3..2)); - Assert.Empty(ToEnumerablePartition(source).Take(6..^5)); - Assert.Empty(ToEnumerablePartition(source).Take(3..^8)); - Assert.Empty(ToEnumerablePartition(source).Take(^6..^7)); + Assert.Empty(EnumerablePartition(source).Take(3..2)); + Assert.Empty(EnumerablePartition(source).Take(6..^5)); + Assert.Empty(EnumerablePartition(source).Take(3..^8)); + Assert.Empty(EnumerablePartition(source).Take(^6..^7)); } [Fact] @@ -1755,50 +1718,50 @@ public void EmptySource_DoNotThrowException_NotList() int[] source = { }; // Multiple elements in the middle. - Assert.Empty(GuaranteeNotIList(source).Take(^9..5)); - Assert.Empty(GuaranteeNotIList(source).Take(2..7)); - Assert.Empty(GuaranteeNotIList(source).Take(2..^4)); - Assert.Empty(GuaranteeNotIList(source).Take(^7..^4)); + 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(GuaranteeNotIList(source).Take(^9..)); - Assert.Empty(GuaranteeNotIList(source).Take(2..)); - Assert.Empty(GuaranteeNotIList(source).Take(..^4)); - Assert.Empty(GuaranteeNotIList(source).Take(..6)); + 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[..], GuaranteeNotIList(source).Take(..)); + Assert.Equal(source[..], ForceNotCollection(source).Take(..)); // Single element in the middle. - Assert.Empty(GuaranteeNotIList(source).Take(^9..2)); - Assert.Empty(GuaranteeNotIList(source).Take(2..3)); - Assert.Empty(GuaranteeNotIList(source).Take(2..^7)); - Assert.Empty(GuaranteeNotIList(source).Take(^5..^4)); + 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(GuaranteeNotIList(source).Take(^10..1)); - Assert.Empty(GuaranteeNotIList(source).Take(0..1)); - Assert.Empty(GuaranteeNotIList(source).Take(0..^9)); - Assert.Empty(GuaranteeNotIList(source).Take(^10..^9)); + 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(GuaranteeNotIList(source).Take(^1..^10)); - Assert.Empty(GuaranteeNotIList(source).Take(9..10)); - Assert.Empty(GuaranteeNotIList(source).Take(9..^9)); - Assert.Empty(GuaranteeNotIList(source).Take(^1..^9)); + 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(GuaranteeNotIList(source).Take(3..3)); - Assert.Empty(GuaranteeNotIList(source).Take(6..^4)); - Assert.Empty(GuaranteeNotIList(source).Take(3..^7)); - Assert.Empty(GuaranteeNotIList(source).Take(^3..7)); - Assert.Empty(GuaranteeNotIList(source).Take(^6..^6)); + 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(GuaranteeNotIList(source).Take(3..2)); - Assert.Empty(GuaranteeNotIList(source).Take(6..^5)); - Assert.Empty(GuaranteeNotIList(source).Take(3..^8)); - Assert.Empty(GuaranteeNotIList(source).Take(^6..^7)); + 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] @@ -1807,50 +1770,50 @@ public void EmptySource_DoNotThrowException_ListPartition() int[] source = { }; // Multiple elements in the middle. - Assert.Empty(ToListPartition(source).Take(^9..5)); - Assert.Empty(ToListPartition(source).Take(2..7)); - Assert.Empty(ToListPartition(source).Take(2..^4)); - Assert.Empty(ToListPartition(source).Take(^7..^4)); + Assert.Empty(ListPartition(source).Take(^9..5)); + Assert.Empty(ListPartition(source).Take(2..7)); + Assert.Empty(ListPartition(source).Take(2..^4)); + Assert.Empty(ListPartition(source).Take(^7..^4)); // Range with default index. - Assert.Empty(ToListPartition(source).Take(^9..)); - Assert.Empty(ToListPartition(source).Take(2..)); - Assert.Empty(ToListPartition(source).Take(..^4)); - Assert.Empty(ToListPartition(source).Take(..6)); + Assert.Empty(ListPartition(source).Take(^9..)); + Assert.Empty(ListPartition(source).Take(2..)); + Assert.Empty(ListPartition(source).Take(..^4)); + Assert.Empty(ListPartition(source).Take(..6)); // All. - Assert.Equal(source[..], ToListPartition(source).Take(..)); + Assert.Equal(source[..], ListPartition(source).Take(..)); // Single element in the middle. - Assert.Empty(ToListPartition(source).Take(^9..2)); - Assert.Empty(ToListPartition(source).Take(2..3)); - Assert.Empty(ToListPartition(source).Take(2..^7)); - Assert.Empty(ToListPartition(source).Take(^5..^4)); + Assert.Empty(ListPartition(source).Take(^9..2)); + Assert.Empty(ListPartition(source).Take(2..3)); + Assert.Empty(ListPartition(source).Take(2..^7)); + Assert.Empty(ListPartition(source).Take(^5..^4)); // Single element at start. - Assert.Empty(ToListPartition(source).Take(^10..1)); - Assert.Empty(ToListPartition(source).Take(0..1)); - Assert.Empty(ToListPartition(source).Take(0..^9)); - Assert.Empty(ToListPartition(source).Take(^10..^9)); + Assert.Empty(ListPartition(source).Take(^10..1)); + Assert.Empty(ListPartition(source).Take(0..1)); + Assert.Empty(ListPartition(source).Take(0..^9)); + Assert.Empty(ListPartition(source).Take(^10..^9)); // Single element at end. - Assert.Empty(ToListPartition(source).Take(^1..^10)); - Assert.Empty(ToListPartition(source).Take(9..10)); - Assert.Empty(ToListPartition(source).Take(9..^9)); - Assert.Empty(ToListPartition(source).Take(^1..^9)); + Assert.Empty(ListPartition(source).Take(^1..^10)); + Assert.Empty(ListPartition(source).Take(9..10)); + Assert.Empty(ListPartition(source).Take(9..^9)); + Assert.Empty(ListPartition(source).Take(^1..^9)); // No element. - Assert.Empty(ToListPartition(source).Take(3..3)); - Assert.Empty(ToListPartition(source).Take(6..^4)); - Assert.Empty(ToListPartition(source).Take(3..^7)); - Assert.Empty(ToListPartition(source).Take(^3..7)); - Assert.Empty(ToListPartition(source).Take(^6..^6)); + Assert.Empty(ListPartition(source).Take(3..3)); + Assert.Empty(ListPartition(source).Take(6..^4)); + Assert.Empty(ListPartition(source).Take(3..^7)); + Assert.Empty(ListPartition(source).Take(^3..7)); + Assert.Empty(ListPartition(source).Take(^6..^6)); // Invalid range. - Assert.Empty(ToListPartition(source).Take(3..2)); - Assert.Empty(ToListPartition(source).Take(6..^5)); - Assert.Empty(ToListPartition(source).Take(3..^8)); - Assert.Empty(ToListPartition(source).Take(^6..^7)); + Assert.Empty(ListPartition(source).Take(3..2)); + Assert.Empty(ListPartition(source).Take(6..^5)); + Assert.Empty(ListPartition(source).Take(3..^8)); + Assert.Empty(ListPartition(source).Take(^6..^7)); } [Fact] @@ -1859,50 +1822,50 @@ public void EmptySource_DoNotThrowException_EnumerablePartition() int[] source = { }; // Multiple elements in the middle. - Assert.Empty(ToEnumerablePartition(source).Take(^9..5)); - Assert.Empty(ToEnumerablePartition(source).Take(2..7)); - Assert.Empty(ToEnumerablePartition(source).Take(2..^4)); - Assert.Empty(ToEnumerablePartition(source).Take(^7..^4)); + Assert.Empty(EnumerablePartition(source).Take(^9..5)); + Assert.Empty(EnumerablePartition(source).Take(2..7)); + Assert.Empty(EnumerablePartition(source).Take(2..^4)); + Assert.Empty(EnumerablePartition(source).Take(^7..^4)); // Range with default index. - Assert.Empty(ToEnumerablePartition(source).Take(^9..)); - Assert.Empty(ToEnumerablePartition(source).Take(2..)); - Assert.Empty(ToEnumerablePartition(source).Take(..^4)); - Assert.Empty(ToEnumerablePartition(source).Take(..6)); + Assert.Empty(EnumerablePartition(source).Take(^9..)); + Assert.Empty(EnumerablePartition(source).Take(2..)); + Assert.Empty(EnumerablePartition(source).Take(..^4)); + Assert.Empty(EnumerablePartition(source).Take(..6)); // All. - Assert.Equal(source[..], ToEnumerablePartition(source).Take(..)); + Assert.Equal(source[..], EnumerablePartition(source).Take(..)); // Single element in the middle. - Assert.Empty(ToEnumerablePartition(source).Take(^9..2)); - Assert.Empty(ToEnumerablePartition(source).Take(2..3)); - Assert.Empty(ToEnumerablePartition(source).Take(2..^7)); - Assert.Empty(ToEnumerablePartition(source).Take(^5..^4)); + Assert.Empty(EnumerablePartition(source).Take(^9..2)); + Assert.Empty(EnumerablePartition(source).Take(2..3)); + Assert.Empty(EnumerablePartition(source).Take(2..^7)); + Assert.Empty(EnumerablePartition(source).Take(^5..^4)); // Single element at start. - Assert.Empty(ToEnumerablePartition(source).Take(^10..1)); - Assert.Empty(ToEnumerablePartition(source).Take(0..1)); - Assert.Empty(ToEnumerablePartition(source).Take(0..^9)); - Assert.Empty(ToEnumerablePartition(source).Take(^10..^9)); + Assert.Empty(EnumerablePartition(source).Take(^10..1)); + Assert.Empty(EnumerablePartition(source).Take(0..1)); + Assert.Empty(EnumerablePartition(source).Take(0..^9)); + Assert.Empty(EnumerablePartition(source).Take(^10..^9)); // Single element at end. - Assert.Empty(ToEnumerablePartition(source).Take(^1..^10)); - Assert.Empty(ToEnumerablePartition(source).Take(9..10)); - Assert.Empty(ToEnumerablePartition(source).Take(9..^9)); - Assert.Empty(ToEnumerablePartition(source).Take(^1..^9)); + Assert.Empty(EnumerablePartition(source).Take(^1..^10)); + Assert.Empty(EnumerablePartition(source).Take(9..10)); + Assert.Empty(EnumerablePartition(source).Take(9..^9)); + Assert.Empty(EnumerablePartition(source).Take(^1..^9)); // No element. - Assert.Empty(ToEnumerablePartition(source).Take(3..3)); - Assert.Empty(ToEnumerablePartition(source).Take(6..^4)); - Assert.Empty(ToEnumerablePartition(source).Take(3..^7)); - Assert.Empty(ToEnumerablePartition(source).Take(^3..7)); - Assert.Empty(ToEnumerablePartition(source).Take(^6..^6)); + Assert.Empty(EnumerablePartition(source).Take(3..3)); + Assert.Empty(EnumerablePartition(source).Take(6..^4)); + Assert.Empty(EnumerablePartition(source).Take(3..^7)); + Assert.Empty(EnumerablePartition(source).Take(^3..7)); + Assert.Empty(EnumerablePartition(source).Take(^6..^6)); // Invalid range. - Assert.Empty(ToEnumerablePartition(source).Take(3..2)); - Assert.Empty(ToEnumerablePartition(source).Take(6..^5)); - Assert.Empty(ToEnumerablePartition(source).Take(3..^8)); - Assert.Empty(ToEnumerablePartition(source).Take(^6..^7)); + Assert.Empty(EnumerablePartition(source).Take(3..2)); + Assert.Empty(EnumerablePartition(source).Take(6..^5)); + Assert.Empty(EnumerablePartition(source).Take(3..^8)); + Assert.Empty(EnumerablePartition(source).Take(^6..^7)); } } } From a11a3dbe664f6057323f4309e2b9120851c0215a Mon Sep 17 00:00:00 2001 From: Dixin Date: Wed, 3 Feb 2021 14:21:20 -0800 Subject: [PATCH 12/35] Implement dotnet/runtime#28776: LINQ APIs for index and range. --- src/libraries/System.Linq/tests/TakeTests.cs | 36 +++++++++++--------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/src/libraries/System.Linq/tests/TakeTests.cs b/src/libraries/System.Linq/tests/TakeTests.cs index 24b9c0666165c6..f81659e448742c 100644 --- a/src/libraries/System.Linq/tests/TakeTests.cs +++ b/src/libraries/System.Linq/tests/TakeTests.cs @@ -8,7 +8,6 @@ namespace System.Linq.Tests { public class TakeTests : EnumerableTests { - [Fact] public void SameResultsRepeatCallsIntQuery() { @@ -1071,25 +1070,25 @@ public void LazyOverflowRegression() Assert.Equal(Enumerable.Range(43, 100 - 42), taken1.ToArray()); Assert.Equal(Enumerable.Range(43, 100 - 42), taken1.ToList()); - var taken2 = NumberRangeGuaranteedNotCollectionType(1, 100).Skip(42).Take(0..int.MaxValue); + 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).Skip(42).Take(^int.MaxValue..int.MaxValue); + 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).Skip(42).Take(int.MaxValue..^0); + 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).Skip(42).Take(^int.MaxValue..^0); + 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()); @@ -1276,29 +1275,32 @@ public void DisposeSource(int sourceCount, int count) // 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[0]); + int expected0 = count <= 0 ? 0 : -1; + Assert.Equal(expected0, state[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()); - Assert.Equal(expected, state[1]); + int expected1 = end == 0 ? 0 : -1; // When startIndex is not from end and endIndex is not from end and startIndex >= endIndex, Take(Range) returns an empty array. + Assert.Equal(expected1, state[1]); IEnumerator iterator2 = source[2].Take(^Math.Max(sourceCount, end)..end).GetEnumerator(); Assert.All(Enumerable.Range(0, Math.Min(sourceCount, Math.Max(0, count))), _ => Assert.True(iterator2.MoveNext())); Assert.False(iterator2.MoveNext()); - Assert.Equal(expected, state[2]); + int expected2 = Math.Max(sourceCount, end) == 0 ? 0 : -1; // When startIndex is ^0, Take(Range) returns an empty iterator. + Assert.Equal(expected2, state[2]); IEnumerator iterator3 = source[3].Take(0..^Math.Max(0, sourceCount - end)).GetEnumerator(); Assert.All(Enumerable.Range(0, Math.Min(sourceCount, Math.Max(0, count))), _ => Assert.True(iterator3.MoveNext())); Assert.False(iterator3.MoveNext()); - Assert.Equal(expected, state[3]); + Assert.Equal(-1, state[3]); IEnumerator iterator4 = source[4].Take(^Math.Max(sourceCount, end)..^Math.Max(0, sourceCount - end)).GetEnumerator(); Assert.All(Enumerable.Range(0, Math.Min(sourceCount, Math.Max(0, count))), _ => Assert.True(iterator4.MoveNext())); Assert.False(iterator4.MoveNext()); - Assert.Equal(expected, state[4]); + int expected4 = Math.Max(sourceCount, end) == 0 ? 0 : -1; // When startIndex is ^0, Take(Range) returns an empty iterator. + Assert.Equal(expected4, state[4]); } [Fact] @@ -1438,16 +1440,16 @@ public void NonEmptySource_ConsistentWithCountable() int[] source = { 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[^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)); + 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)); + 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(..)); From 4711c9a7a0f68beaf696dd44ae63c0c3050b2e6b Mon Sep 17 00:00:00 2001 From: Dixin Date: Thu, 4 Feb 2021 04:07:47 -0800 Subject: [PATCH 13/35] Implement dotnet/runtime#28776: LINQ APIs for index and range. --- .../System.Linq/src/System/Linq/ElementAt.cs | 79 ++++++++++++------- .../System.Linq/src/System/Linq/Take.cs | 8 ++ 2 files changed, 59 insertions(+), 28 deletions(-) diff --git a/src/libraries/System.Linq/src/System/Linq/ElementAt.cs b/src/libraries/System.Linq/src/System/Linq/ElementAt.cs index b902699ea9db85..12a2899f466efe 100644 --- a/src/libraries/System.Linq/src/System/Linq/ElementAt.cs +++ b/src/libraries/System.Linq/src/System/Linq/ElementAt.cs @@ -50,6 +50,15 @@ public static TSource ElementAt(this IEnumerable source, int i 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 sequence. + /// The element at the specified position in the source sequence. public static TSource ElementAt(this IEnumerable source, Index index) { if (source == null) @@ -68,16 +77,21 @@ public static TSource ElementAt(this IEnumerable source, Index if (source is IPartition partition) { int count = partition.GetCount(onlyIfCheap: true); - if (count > 0) + if (count == 0) { - TSource? element = partition.TryGetElementAt(count - indexFromEnd, out bool found); - if (found) - { - return element!; - } + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); } - else if (count == 0) + else if (count > 0) { + if (indexFromEnd <= count) + { + TSource? element = partition.TryGetElementAt(count - indexFromEnd, out bool found); + if (found) + { + return element!; + } + } + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); } } @@ -153,6 +167,14 @@ public static TSource ElementAt(this IEnumerable source, Index return default; } + /// 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 source sequence; otherwise, the element at the specified position in the source sequence. public static TSource? ElementAtOrDefault(this IEnumerable source, Index index) { if (source == null) @@ -171,17 +193,16 @@ public static TSource ElementAt(this IEnumerable source, Index if (source is IPartition partition) { int count = partition.GetCount(onlyIfCheap: true); - if (count > 0) + if (count == 0) { - TSource? element = partition.TryGetElementAt(count - indexFromEnd, out bool found); - if (found) - { - return element!; - } + return default; } - else if (count == 0) + + if (count > 0) { - return default; + return indexFromEnd <= count + ? partition.TryGetElementAt(count - indexFromEnd, out bool _) + : default; } } else if (source is IList list) @@ -191,24 +212,26 @@ public static TSource ElementAt(this IEnumerable source, Index } using IEnumerator e = source.GetEnumerator(); - if (e.MoveNext()) + if (!e.MoveNext()) { - Queue queue = new(); - queue.Enqueue(e.Current); - while (e.MoveNext()) - { - if (queue.Count == indexFromEnd) - { - queue.Dequeue(); - } - - queue.Enqueue(e.Current); - } + return default; + } + Queue queue = new(); + queue.Enqueue(e.Current); + while (e.MoveNext()) + { if (queue.Count == indexFromEnd) { - return queue.Dequeue(); + queue.Dequeue(); } + + queue.Enqueue(e.Current); + } + + if (queue.Count == indexFromEnd) + { + return queue.Dequeue(); } } diff --git a/src/libraries/System.Linq/src/System/Linq/Take.cs b/src/libraries/System.Linq/src/System/Linq/Take.cs index be41f5df55f451..7d3be8a2e5eea5 100644 --- a/src/libraries/System.Linq/src/System/Linq/Take.cs +++ b/src/libraries/System.Linq/src/System/Linq/Take.cs @@ -20,6 +20,14 @@ 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 range of elements from the source sequence. public static IEnumerable Take(this IEnumerable source, Range range) { if (source == null) From 3d664110c087012738d000d9f39ff65db1d5c7a3 Mon Sep 17 00:00:00 2001 From: Dixin Date: Thu, 4 Feb 2021 06:09:35 -0800 Subject: [PATCH 14/35] Implement dotnet/runtime#28776: LINQ APIs for index and range. --- .../src/System/Linq/Queryable.cs | 29 +++++++++++++++++++ .../System.Linq/src/System/Linq/ElementAt.cs | 11 ++++--- .../System.Linq/src/System/Linq/Take.cs | 2 +- 3 files changed, 37 insertions(+), 5 deletions(-) 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 7f3a996ec5c5e8..fe839723f50c88 100644 --- a/src/libraries/System.Linq.Queryable/src/System/Linq/Queryable.cs +++ b/src/libraries/System.Linq.Queryable/src/System/Linq/Queryable.cs @@ -389,6 +389,14 @@ public static IQueryable Take(this IQueryable source, )); } + /// 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) { @@ -973,6 +981,17 @@ public static TSource ElementAt(this IQueryable source, int in )); } + /// 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) { @@ -1001,6 +1020,16 @@ public static TSource ElementAt(this IQueryable source, 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) { diff --git a/src/libraries/System.Linq/src/System/Linq/ElementAt.cs b/src/libraries/System.Linq/src/System/Linq/ElementAt.cs index 12a2899f466efe..94f7ddd1845514 100644 --- a/src/libraries/System.Linq/src/System/Linq/ElementAt.cs +++ b/src/libraries/System.Linq/src/System/Linq/ElementAt.cs @@ -57,8 +57,9 @@ public static TSource ElementAt(this IEnumerable source, int i /// /// is . /// - /// is outside the bounds of sequence. - /// The element at the specified position in the source sequence. + /// 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) @@ -172,9 +173,11 @@ public static TSource ElementAt(this IEnumerable source, Index /// The index of the element to retrieve, which is either from the start or the end. /// The type of the elements of . /// - /// is . + /// is . + /// /// - /// if index is outside the bounds of the source sequence; otherwise, the element at the specified position in the source sequence. + /// 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) diff --git a/src/libraries/System.Linq/src/System/Linq/Take.cs b/src/libraries/System.Linq/src/System/Linq/Take.cs index 7d3be8a2e5eea5..dab4bd724da06c 100644 --- a/src/libraries/System.Linq/src/System/Linq/Take.cs +++ b/src/libraries/System.Linq/src/System/Linq/Take.cs @@ -27,7 +27,7 @@ public static IEnumerable Take(this IEnumerable sourc /// /// is . /// - /// An that contains the specified range of elements from the source sequence. + /// An that contains the specified of elements from the sequence. public static IEnumerable Take(this IEnumerable source, Range range) { if (source == null) From fdabe87184a854f7a7731840ff60eed6da72bae8 Mon Sep 17 00:00:00 2001 From: Dixin Date: Thu, 4 Feb 2021 18:29:40 -0800 Subject: [PATCH 15/35] Implement dotnet/runtime#28776: LINQ APIs for index and range. --- .../System.Linq/src/System/Linq/ElementAt.cs | 137 +++++----- .../System.Linq/src/System/Linq/Take.cs | 2 + .../tests/ElementAtOrDefaultTests.cs | 256 +++++++++++++++++- .../System.Linq/tests/ElementAtTests.cs | 248 ++++++++++++++++- src/libraries/System.Linq/tests/TakeTests.cs | 8 +- 5 files changed, 572 insertions(+), 79 deletions(-) diff --git a/src/libraries/System.Linq/src/System/Linq/ElementAt.cs b/src/libraries/System.Linq/src/System/Linq/ElementAt.cs index 94f7ddd1845514..7de94845e8eca2 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; namespace System.Linq { @@ -73,53 +74,57 @@ public static TSource ElementAt(this IEnumerable source, Index } int indexFromEnd = index.Value; - if (indexFromEnd > 0) + Debug.Assert(indexFromEnd >= 0); + if (indexFromEnd == 0) { - if (source is IPartition partition) - { - int count = partition.GetCount(onlyIfCheap: true); - if (count == 0) - { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); - } - else if (count > 0) - { - if (indexFromEnd <= count) - { - TSource? element = partition.TryGetElementAt(count - indexFromEnd, out bool found); - if (found) - { - return element!; - } - } + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); + } - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); - } - } - else if (source is IList list) + if (source is IPartition partition) + { + int count = partition.GetCount(onlyIfCheap: true); + if (count == 0) { - return list[index]; + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); } - using IEnumerator e = source.GetEnumerator(); - if (e.MoveNext()) + if (count > 0) { - Queue queue = new(); - queue.Enqueue(e.Current); - while (e.MoveNext()) + if (indexFromEnd <= count) { - if (queue.Count == indexFromEnd) + TSource? element = partition.TryGetElementAt(count - indexFromEnd, out bool found); + if (found) { - queue.Dequeue(); + return element!; } - - queue.Enqueue(e.Current); } + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); + } + } + else if (source is IList list) + { + return list[index]; + } + + using IEnumerator e = source.GetEnumerator(); + if (e.MoveNext()) + { + Queue queue = new(); + queue.Enqueue(e.Current); + while (e.MoveNext()) + { if (queue.Count == indexFromEnd) { - return queue.Dequeue(); + queue.Dequeue(); } + + queue.Enqueue(e.Current); + } + + if (queue.Count == indexFromEnd) + { + return queue.Dequeue(); } } @@ -191,54 +196,52 @@ public static TSource ElementAt(this IEnumerable source, Index } int indexFromEnd = index.Value; - if (indexFromEnd > 0) + Debug.Assert(indexFromEnd >= 0); + if (indexFromEnd == 0) { - if (source is IPartition partition) - { - int count = partition.GetCount(onlyIfCheap: true); - if (count == 0) - { - return default; - } - - if (count > 0) - { - return indexFromEnd <= count - ? partition.TryGetElementAt(count - indexFromEnd, out bool _) - : default; - } - } - else if (source is IList list) - { - int count = list.Count; - return indexFromEnd <= count ? list[count - indexFromEnd] : default; - } + return default; + } - using IEnumerator e = source.GetEnumerator(); - if (!e.MoveNext()) + if (source is IPartition partition) + { + int count = partition.GetCount(onlyIfCheap: true); + if (count == 0) { return default; } - Queue queue = new(); - queue.Enqueue(e.Current); - while (e.MoveNext()) + if (count > 0) { - if (queue.Count == indexFromEnd) - { - queue.Dequeue(); - } - - queue.Enqueue(e.Current); + return indexFromEnd <= count + ? partition.TryGetElementAt(count - indexFromEnd, out bool _) + : default; } + } + else if (source is IList list) + { + int count = list.Count; + return indexFromEnd <= count ? list[count - indexFromEnd] : default; + } + using IEnumerator e = source.GetEnumerator(); + if (!e.MoveNext()) + { + return default; + } + + Queue queue = new(); + queue.Enqueue(e.Current); + while (e.MoveNext()) + { if (queue.Count == indexFromEnd) { - return queue.Dequeue(); + queue.Dequeue(); } + + queue.Enqueue(e.Current); } - return default; + return queue.Count == indexFromEnd ? queue.Dequeue() : default; } } } diff --git a/src/libraries/System.Linq/src/System/Linq/Take.cs b/src/libraries/System.Linq/src/System/Linq/Take.cs index dab4bd724da06c..260bb10bc82314 100644 --- a/src/libraries/System.Linq/src/System/Linq/Take.cs +++ b/src/libraries/System.Linq/src/System/Linq/Take.cs @@ -41,6 +41,8 @@ public static IEnumerable Take(this IEnumerable sourc bool isEndIndexFromEnd = end.IsFromEnd; int startIndex = start.Value; int endIndex = end.Value; + Debug.Assert(startIndex >= 0); + Debug.Assert(endIndex >= 0); if (!isStartIndexFromEnd && !isEndIndexFromEnd) { diff --git a/src/libraries/System.Linq/tests/ElementAtOrDefaultTests.cs b/src/libraries/System.Linq/tests/ElementAtOrDefaultTests.cs index 55d93850330328..bfcbe48c86c337 100644 --- a/src/libraries/System.Linq/tests/ElementAtOrDefaultTests.cs +++ b/src/libraries/System.Linq/tests/ElementAtOrDefaultTests.cs @@ -12,8 +12,8 @@ public class ElementAtOrDefaultTests : EnumerableTests public void SameResultsRepeatCallsIntQuery() { var q = Repeat(_ => from x in new[] { 9999, 0, 888, -1, 66, -777, 1, 2, -12345 } - where x > int.MinValue - select x, 3); + 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)); @@ -23,8 +23,8 @@ where x > int.MinValue public void SameResultsRepeatCallsStringQuery() { var q = Repeat(_ => from x in new[] { "!@#$%^", "C", "AAA", "", "Calling Twice", "SoS", string.Empty } - where !string.IsNullOrEmpty(x) - select x, 3); + 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)); @@ -111,5 +111,253 @@ public void NullSource_ThrowsArgumentNullException() AssertExtensions.Throws("source", () => ((IEnumerable)null).ElementAtOrDefault(new Index(2))); AssertExtensions.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 NonEmptySource_Consistency() + { + int?[] source = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + int? @null = null; + + 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.Equal(@null, source.ElementAtOrDefault(-1)); + Assert.Equal(@null, source.ElementAtOrDefault(^11)); + + Assert.Equal(@null, source.ElementAtOrDefault(10)); + Assert.Equal(@null, source.ElementAtOrDefault(new Index(10))); + Assert.Equal(@null, source.ElementAtOrDefault(^0)); + + Assert.Equal(@null, source.ElementAtOrDefault(int.MinValue)); + Assert.Equal(@null, source.ElementAtOrDefault(^int.MaxValue)); + + Assert.Equal(@null, source.ElementAtOrDefault(int.MaxValue)); + Assert.Equal(@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 }; + int? @null = null; + + 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.Equal(@null, ForceNotCollection(source).ElementAtOrDefault(-1)); + Assert.Equal(@null, ForceNotCollection(source).ElementAtOrDefault(^11)); + + Assert.Equal(@null, ForceNotCollection(source).ElementAtOrDefault(10)); + Assert.Equal(@null, ForceNotCollection(source).ElementAtOrDefault(new Index(10))); + Assert.Equal(@null, ForceNotCollection(source).ElementAtOrDefault(^0)); + + Assert.Equal(@null, ForceNotCollection(source).ElementAtOrDefault(int.MinValue)); + Assert.Equal(@null, ForceNotCollection(source).ElementAtOrDefault(^int.MaxValue)); + + Assert.Equal(@null, ForceNotCollection(source).ElementAtOrDefault(int.MaxValue)); + Assert.Equal(@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 }; + int? @null = null; + + Assert.Equal(5, ListPartition(source).ElementAtOrDefault(5)); + Assert.Equal(5, ListPartition(source).ElementAtOrDefault(new Index(5))); + Assert.Equal(5, ListPartition(source).ElementAtOrDefault(^5)); + + Assert.Equal(0, ListPartition(source).ElementAtOrDefault(0)); + Assert.Equal(0, ListPartition(source).ElementAtOrDefault(new Index(0))); + Assert.Equal(0, ListPartition(source).ElementAtOrDefault(^10)); + + Assert.Equal(9, ListPartition(source).ElementAtOrDefault(9)); + Assert.Equal(9, ListPartition(source).ElementAtOrDefault(new Index(9))); + Assert.Equal(9, ListPartition(source).ElementAtOrDefault(^1)); + + Assert.Equal(@null, ListPartition(source).ElementAtOrDefault(-1)); + Assert.Equal(@null, ListPartition(source).ElementAtOrDefault(^11)); + + Assert.Equal(@null, ListPartition(source).ElementAtOrDefault(10)); + Assert.Equal(@null, ListPartition(source).ElementAtOrDefault(new Index(10))); + Assert.Equal(@null, ListPartition(source).ElementAtOrDefault(^0)); + + Assert.Equal(@null, ListPartition(source).ElementAtOrDefault(int.MinValue)); + Assert.Equal(@null, ListPartition(source).ElementAtOrDefault(^int.MaxValue)); + + Assert.Equal(@null, ListPartition(source).ElementAtOrDefault(int.MaxValue)); + Assert.Equal(@null, ListPartition(source).ElementAtOrDefault(new Index(int.MaxValue))); + } + + [Fact] + public void NonEmptySource_Consistency_EnumerablePartition() + { + int?[] source = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + int? @null = null; + + Assert.Equal(5, EnumerablePartition(source).ElementAtOrDefault(5)); + Assert.Equal(5, EnumerablePartition(source).ElementAtOrDefault(new Index(5))); + Assert.Equal(5, EnumerablePartition(source).ElementAtOrDefault(^5)); + + Assert.Equal(0, EnumerablePartition(source).ElementAtOrDefault(0)); + Assert.Equal(0, EnumerablePartition(source).ElementAtOrDefault(new Index(0))); + Assert.Equal(0, EnumerablePartition(source).ElementAtOrDefault(^10)); + + Assert.Equal(9, EnumerablePartition(source).ElementAtOrDefault(9)); + Assert.Equal(9, EnumerablePartition(source).ElementAtOrDefault(new Index(9))); + Assert.Equal(9, EnumerablePartition(source).ElementAtOrDefault(^1)); + + Assert.Equal(@null, EnumerablePartition(source).ElementAtOrDefault(-1)); + Assert.Equal(@null, EnumerablePartition(source).ElementAtOrDefault(^11)); + + Assert.Equal(@null, EnumerablePartition(source).ElementAtOrDefault(10)); + Assert.Equal(@null, EnumerablePartition(source).ElementAtOrDefault(new Index(10))); + Assert.Equal(@null, EnumerablePartition(source).ElementAtOrDefault(^0)); + + Assert.Equal(@null, EnumerablePartition(source).ElementAtOrDefault(int.MinValue)); + Assert.Equal(@null, EnumerablePartition(source).ElementAtOrDefault(^int.MaxValue)); + + Assert.Equal(@null, EnumerablePartition(source).ElementAtOrDefault(int.MaxValue)); + Assert.Equal(@null, EnumerablePartition(source).ElementAtOrDefault(new Index(int.MaxValue))); + } + + [Fact] + public void EmptySource_Consistency() + { + int?[] source = { }; + int? @null = null; + + Assert.Equal(@null, source.ElementAtOrDefault(1)); + Assert.Equal(@null, source.ElementAtOrDefault(-1)); + Assert.Equal(@null, source.ElementAtOrDefault(new Index(1))); + Assert.Equal(@null, source.ElementAtOrDefault(^1)); + + Assert.Equal(@null, source.ElementAtOrDefault(0)); + Assert.Equal(@null, source.ElementAtOrDefault(new Index(0))); + Assert.Equal(@null, source.ElementAtOrDefault(^0)); + + Assert.Equal(@null, source.ElementAtOrDefault(int.MinValue)); + Assert.Equal(@null, source.ElementAtOrDefault(^int.MaxValue)); + + Assert.Equal(@null, source.ElementAtOrDefault(int.MaxValue)); + Assert.Equal(@null, source.ElementAtOrDefault(new Index(int.MaxValue))); + } + + [Fact] + public void EmptySource_Consistency_NotList() + { + int?[] source = { }; + int? @null = null; + + Assert.Equal(@null, ForceNotCollection(source).ElementAtOrDefault(1)); + Assert.Equal(@null, ForceNotCollection(source).ElementAtOrDefault(-1)); + Assert.Equal(@null, ForceNotCollection(source).ElementAtOrDefault(new Index(1))); + Assert.Equal(@null, ForceNotCollection(source).ElementAtOrDefault(^1)); + + Assert.Equal(@null, ForceNotCollection(source).ElementAtOrDefault(0)); + Assert.Equal(@null, ForceNotCollection(source).ElementAtOrDefault(new Index(0))); + Assert.Equal(@null, ForceNotCollection(source).ElementAtOrDefault(^0)); + + Assert.Equal(@null, ForceNotCollection(source).ElementAtOrDefault(int.MinValue)); + Assert.Equal(@null, ForceNotCollection(source).ElementAtOrDefault(^int.MaxValue)); + + Assert.Equal(@null, ForceNotCollection(source).ElementAtOrDefault(int.MaxValue)); + Assert.Equal(@null, ForceNotCollection(source).ElementAtOrDefault(new Index(int.MaxValue))); + } + + [Fact] + public void EmptySource_Consistency_ListPartition() + { + int?[] source = { }; + int? @null = null; + + Assert.Equal(@null, ListPartition(source).ElementAtOrDefault(1)); + Assert.Equal(@null, ListPartition(source).ElementAtOrDefault(-1)); + Assert.Equal(@null, ListPartition(source).ElementAtOrDefault(new Index(1))); + Assert.Equal(@null, ListPartition(source).ElementAtOrDefault(^1)); + + Assert.Equal(@null, ListPartition(source).ElementAtOrDefault(0)); + Assert.Equal(@null, ListPartition(source).ElementAtOrDefault(new Index(0))); + Assert.Equal(@null, ListPartition(source).ElementAtOrDefault(^0)); + + Assert.Equal(@null, ListPartition(source).ElementAtOrDefault(int.MinValue)); + Assert.Equal(@null, ListPartition(source).ElementAtOrDefault(^int.MaxValue)); + + Assert.Equal(@null, ListPartition(source).ElementAtOrDefault(int.MaxValue)); + Assert.Equal(@null, ListPartition(source).ElementAtOrDefault(new Index(int.MaxValue))); + } + + [Fact] + public void EmptySource_Consistency_EnumerablePartition() + { + int?[] source = { }; + int? @null = null; + + Assert.Equal(@null, EnumerablePartition(source).ElementAtOrDefault(1)); + Assert.Equal(@null, EnumerablePartition(source).ElementAtOrDefault(-1)); + Assert.Equal(@null, EnumerablePartition(source).ElementAtOrDefault(new Index(1))); + Assert.Equal(@null, EnumerablePartition(source).ElementAtOrDefault(^1)); + + Assert.Equal(@null, EnumerablePartition(source).ElementAtOrDefault(0)); + Assert.Equal(@null, EnumerablePartition(source).ElementAtOrDefault(new Index(0))); + Assert.Equal(@null, EnumerablePartition(source).ElementAtOrDefault(^0)); + + Assert.Equal(@null, EnumerablePartition(source).ElementAtOrDefault(int.MinValue)); + Assert.Equal(@null, EnumerablePartition(source).ElementAtOrDefault(^int.MaxValue)); + + Assert.Equal(@null, EnumerablePartition(source).ElementAtOrDefault(int.MaxValue)); + Assert.Equal(@null, EnumerablePartition(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 8c3e2ffb32d3cd..979925ed3e8df7 100644 --- a/src/libraries/System.Linq/tests/ElementAtTests.cs +++ b/src/libraries/System.Linq/tests/ElementAtTests.cs @@ -12,8 +12,8 @@ public class ElementAtTests : EnumerableTests public void SameResultsRepeatCallsIntQuery() { var q = Repeat(_ => from x in new[] { 9999, 0, 888, -1, 66, -777, 1, 2, -12345 } - where x > int.MinValue - select x, 3); + 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)); @@ -23,8 +23,8 @@ where x > int.MinValue public void SameResultsRepeatCallsStringQuery() { var q = Repeat(_ => from x in new[] { "!@#$%^", "C", "AAA", "", "Calling Twice", "SoS", string.Empty } - where !string.IsNullOrEmpty(x) - select x,3); + 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)); @@ -117,5 +117,245 @@ public void NullSource_ThrowsArgumentNullException() AssertExtensions.Throws("source", () => ((IEnumerable)null).ElementAt(new Index(2))); AssertExtensions.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 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)); + + AssertExtensions.Throws("index", () => source.ElementAt(-1)); + AssertExtensions.Throws("index", () => source.ElementAt(^11)); + + AssertExtensions.Throws("index", () => source.ElementAt(10)); + AssertExtensions.Throws("index", () => source.ElementAt(new Index(10))); + AssertExtensions.Throws("index", () => source.ElementAt(^0)); + + AssertExtensions.Throws("index", () => source.ElementAt(int.MinValue)); + AssertExtensions.Throws("index", () => source.ElementAt(^int.MaxValue)); + + AssertExtensions.Throws("index", () => source.ElementAt(int.MaxValue)); + AssertExtensions.Throws("index", () => source.ElementAt(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).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)); + + AssertExtensions.Throws("index", () => ForceNotCollection(source).ElementAt(-1)); + AssertExtensions.Throws("index", () => ForceNotCollection(source).ElementAt(^11)); + + AssertExtensions.Throws("index", () => ForceNotCollection(source).ElementAt(10)); + AssertExtensions.Throws("index", () => ForceNotCollection(source).ElementAt(new Index(10))); + AssertExtensions.Throws("index", () => ForceNotCollection(source).ElementAt(^0)); + + AssertExtensions.Throws("index", () => ForceNotCollection(source).ElementAt(int.MinValue)); + AssertExtensions.Throws("index", () => ForceNotCollection(source).ElementAt(^int.MaxValue)); + + AssertExtensions.Throws("index", () => ForceNotCollection(source).ElementAt(int.MaxValue)); + AssertExtensions.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, ListPartition(source).ElementAt(5)); + Assert.Equal(5, ListPartition(source).ElementAt(new Index(5))); + Assert.Equal(5, ListPartition(source).ElementAt(^5)); + + Assert.Equal(0, ListPartition(source).ElementAt(0)); + Assert.Equal(0, ListPartition(source).ElementAt(new Index(0))); + Assert.Equal(0, ListPartition(source).ElementAt(^10)); + + Assert.Equal(9, ListPartition(source).ElementAt(9)); + Assert.Equal(9, ListPartition(source).ElementAt(new Index(9))); + Assert.Equal(9, ListPartition(source).ElementAt(^1)); + + AssertExtensions.Throws("index", () => ListPartition(source).ElementAt(-1)); + AssertExtensions.Throws("index", () => ListPartition(source).ElementAt(^11)); + + AssertExtensions.Throws("index", () => ListPartition(source).ElementAt(10)); + AssertExtensions.Throws("index", () => ListPartition(source).ElementAt(new Index(10))); + AssertExtensions.Throws("index", () => ListPartition(source).ElementAt(^0)); + + AssertExtensions.Throws("index", () => ListPartition(source).ElementAt(int.MinValue)); + AssertExtensions.Throws("index", () => ListPartition(source).ElementAt(^int.MaxValue)); + + AssertExtensions.Throws("index", () => ListPartition(source).ElementAt(int.MaxValue)); + AssertExtensions.Throws("index", () => ListPartition(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, EnumerablePartition(source).ElementAt(5)); + Assert.Equal(5, EnumerablePartition(source).ElementAt(new Index(5))); + Assert.Equal(5, EnumerablePartition(source).ElementAt(^5)); + + Assert.Equal(0, EnumerablePartition(source).ElementAt(0)); + Assert.Equal(0, EnumerablePartition(source).ElementAt(new Index(0))); + Assert.Equal(0, EnumerablePartition(source).ElementAt(^10)); + + Assert.Equal(9, EnumerablePartition(source).ElementAt(9)); + Assert.Equal(9, EnumerablePartition(source).ElementAt(new Index(9))); + Assert.Equal(9, EnumerablePartition(source).ElementAt(^1)); + + AssertExtensions.Throws("index", () => EnumerablePartition(source).ElementAt(-1)); + AssertExtensions.Throws("index", () => EnumerablePartition(source).ElementAt(^11)); + + AssertExtensions.Throws("index", () => EnumerablePartition(source).ElementAt(10)); + AssertExtensions.Throws("index", () => EnumerablePartition(source).ElementAt(new Index(10))); + AssertExtensions.Throws("index", () => EnumerablePartition(source).ElementAt(^0)); + + AssertExtensions.Throws("index", () => EnumerablePartition(source).ElementAt(int.MinValue)); + AssertExtensions.Throws("index", () => EnumerablePartition(source).ElementAt(^int.MaxValue)); + + AssertExtensions.Throws("index", () => EnumerablePartition(source).ElementAt(int.MaxValue)); + AssertExtensions.Throws("index", () => EnumerablePartition(source).ElementAt(new Index(int.MaxValue))); + } + + [Fact] + public void EmptySource_Consistency() + { + int[] source = { }; + + AssertExtensions.Throws("index", () => source.ElementAt(1)); + AssertExtensions.Throws("index", () => source.ElementAt(-1)); + AssertExtensions.Throws("index", () => source.ElementAt(new Index(1))); + AssertExtensions.Throws("index", () => source.ElementAt(^1)); + + AssertExtensions.Throws("index", () => source.ElementAt(0)); + AssertExtensions.Throws("index", () => source.ElementAt(new Index(0))); + AssertExtensions.Throws("index", () => source.ElementAt(^0)); + + AssertExtensions.Throws("index", () => source.ElementAt(int.MinValue)); + AssertExtensions.Throws("index", () => source.ElementAt(^int.MaxValue)); + + AssertExtensions.Throws("index", () => source.ElementAt(int.MaxValue)); + AssertExtensions.Throws("index", () => source.ElementAt(new Index(int.MaxValue))); + } + + [Fact] + public void EmptySource_Consistency_NotList() + { + int[] source = { }; + + AssertExtensions.Throws("index", () => ForceNotCollection(source).ElementAt(1)); + AssertExtensions.Throws("index", () => ForceNotCollection(source).ElementAt(-1)); + AssertExtensions.Throws("index", () => ForceNotCollection(source).ElementAt(new Index(1))); + AssertExtensions.Throws("index", () => ForceNotCollection(source).ElementAt(^1)); + + AssertExtensions.Throws("index", () => ForceNotCollection(source).ElementAt(0)); + AssertExtensions.Throws("index", () => ForceNotCollection(source).ElementAt(new Index(0))); + AssertExtensions.Throws("index", () => ForceNotCollection(source).ElementAt(^0)); + + AssertExtensions.Throws("index", () => ForceNotCollection(source).ElementAt(int.MinValue)); + AssertExtensions.Throws("index", () => ForceNotCollection(source).ElementAt(^int.MaxValue)); + + AssertExtensions.Throws("index", () => ForceNotCollection(source).ElementAt(int.MaxValue)); + AssertExtensions.Throws("index", () => ForceNotCollection(source).ElementAt(new Index(int.MaxValue))); + } + + [Fact] + public void EmptySource_Consistency_ListPartition() + { + int[] source = { }; + + AssertExtensions.Throws("index", () => ListPartition(source).ElementAt(1)); + AssertExtensions.Throws("index", () => ListPartition(source).ElementAt(-1)); + AssertExtensions.Throws("index", () => ListPartition(source).ElementAt(new Index(1))); + AssertExtensions.Throws("index", () => ListPartition(source).ElementAt(^1)); + + AssertExtensions.Throws("index", () => ListPartition(source).ElementAt(0)); + AssertExtensions.Throws("index", () => ListPartition(source).ElementAt(new Index(0))); + AssertExtensions.Throws("index", () => ListPartition(source).ElementAt(^0)); + + AssertExtensions.Throws("index", () => ListPartition(source).ElementAt(int.MinValue)); + AssertExtensions.Throws("index", () => ListPartition(source).ElementAt(^int.MaxValue)); + + AssertExtensions.Throws("index", () => ListPartition(source).ElementAt(int.MaxValue)); + AssertExtensions.Throws("index", () => ListPartition(source).ElementAt(new Index(int.MaxValue))); + } + + [Fact] + public void EmptySource_Consistency_EnumerablePartition() + { + int[] source = { }; + + AssertExtensions.Throws("index", () => EnumerablePartition(source).ElementAt(1)); + AssertExtensions.Throws("index", () => EnumerablePartition(source).ElementAt(-1)); + AssertExtensions.Throws("index", () => EnumerablePartition(source).ElementAt(new Index(1))); + AssertExtensions.Throws("index", () => EnumerablePartition(source).ElementAt(^1)); + + AssertExtensions.Throws("index", () => EnumerablePartition(source).ElementAt(0)); + AssertExtensions.Throws("index", () => EnumerablePartition(source).ElementAt(new Index(0))); + AssertExtensions.Throws("index", () => EnumerablePartition(source).ElementAt(^0)); + + AssertExtensions.Throws("index", () => EnumerablePartition(source).ElementAt(int.MinValue)); + AssertExtensions.Throws("index", () => EnumerablePartition(source).ElementAt(^int.MaxValue)); + + AssertExtensions.Throws("index", () => EnumerablePartition(source).ElementAt(int.MaxValue)); + AssertExtensions.Throws("index", () => EnumerablePartition(source).ElementAt(new Index(int.MaxValue))); + } } } diff --git a/src/libraries/System.Linq/tests/TakeTests.cs b/src/libraries/System.Linq/tests/TakeTests.cs index f81659e448742c..c98944b24b5581 100644 --- a/src/libraries/System.Linq/tests/TakeTests.cs +++ b/src/libraries/System.Linq/tests/TakeTests.cs @@ -1435,7 +1435,7 @@ public void MutableSourceNotList() } [Fact] - public void NonEmptySource_ConsistentWithCountable() + public void NonEmptySource_ConsistencyWithCountable() { int[] source = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; @@ -1481,7 +1481,7 @@ public void NonEmptySource_ConsistentWithCountable() } [Fact] - public void NonEmptySource_ConsistentWithCountable_NotList() + public void NonEmptySource_ConsistencyWithCountable_NotList() { int[] source = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; @@ -1527,7 +1527,7 @@ public void NonEmptySource_ConsistentWithCountable_NotList() } [Fact] - public void NonEmptySource_ConsistentWithCountable_ListPartition() + public void NonEmptySource_ConsistencyWithCountable_ListPartition() { int[] source = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; @@ -1573,7 +1573,7 @@ public void NonEmptySource_ConsistentWithCountable_ListPartition() } [Fact] - public void NonEmptySource_ConsistentWithCountable_EnumerablePartition() + public void NonEmptySource_ConsistencyWithCountable_EnumerablePartition() { int[] source = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; From 683a2ed8ddf4dcf62c45b960bf766002d89e1768 Mon Sep 17 00:00:00 2001 From: Dixin Date: Fri, 5 Feb 2021 11:28:28 -0800 Subject: [PATCH 16/35] Implement dotnet/runtime#28776: LINQ APIs for index and range. --- .../src/System/Linq/CachedReflection.cs | 390 ++++++------------ 1 file changed, 130 insertions(+), 260 deletions(-) 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 e7cbb7c3a3b3a2..d1c1050bcf2a28 100644 --- a/src/libraries/System.Linq.Queryable/src/System/Linq/CachedReflection.cs +++ b/src/libraries/System.Linq.Queryable/src/System/Linq/CachedReflection.cs @@ -12,892 +12,762 @@ 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_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_Int32_TSource_2; public static MethodInfo ElementAt_Int32_TSource_2(Type TSource) => - (s_ElementAt_Int32_TSource_2 ?? - (s_ElementAt_Int32_TSource_2 = new Func, int, object>(Queryable.ElementAt).GetMethodInfo().GetGenericMethodDefinition())) + (s_ElementAt_Int32_TSource_2 ??= new Func, int, object>(Queryable.ElementAt).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_ElementAt_Index_TSource_2; public static MethodInfo ElementAt_Index_TSource_2(Type TSource) => - (s_ElementAt_Index_TSource_2 ?? - (s_ElementAt_Index_TSource_2 = new Func, Index, object>(Queryable.ElementAt).GetMethodInfo().GetGenericMethodDefinition())) + (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 ?? - (s_ElementAtOrDefault_Int32_TSource_2 = new Func, int, object?>(Queryable.ElementAtOrDefault).GetMethodInfo().GetGenericMethodDefinition())) + (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 ?? - (s_ElementAtOrDefault_Index_TSource_2 = new Func, Index, object?>(Queryable.ElementAtOrDefault).GetMethodInfo().GetGenericMethodDefinition())) + (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 ?? - (s_Take_Int32_TSource_2 = new Func, int, IQueryable>(Queryable.Take).GetMethodInfo().GetGenericMethodDefinition())) + (s_Take_Int32_TSource_2 ??= new Func, int, IQueryable>(Queryable.Take).GetMethodInfo().GetGenericMethodDefinition()) .MakeGenericMethod(TSource); private static MethodInfo? s_Take_Range_TSource_2; public static MethodInfo Take_Range_TSource_2(Type TSource) => - (s_Take_Range_TSource_2 ?? - (s_Take_Range_TSource_2 = new Func, Range, IQueryable>(Queryable.Take).GetMethodInfo().GetGenericMethodDefinition())) + (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); } } From ee4dff1d715c05a0c52ca6e8b356e0e42e2bd76a Mon Sep 17 00:00:00 2001 From: Dixin Date: Fri, 5 Feb 2021 18:58:29 -0800 Subject: [PATCH 17/35] Implement dotnet/runtime#28776: LINQ APIs for index and range. --- .../tests/ElementAtOrDefaultTests.cs | 172 +-- src/libraries/System.Linq/tests/TakeTests.cs | 1321 +++++++++-------- 2 files changed, 785 insertions(+), 708 deletions(-) diff --git a/src/libraries/System.Linq/tests/ElementAtOrDefaultTests.cs b/src/libraries/System.Linq/tests/ElementAtOrDefaultTests.cs index bfcbe48c86c337..a511b28cc4237e 100644 --- a/src/libraries/System.Linq/tests/ElementAtOrDefaultTests.cs +++ b/src/libraries/System.Linq/tests/ElementAtOrDefaultTests.cs @@ -52,7 +52,7 @@ public void ElementAtOrDefault(IEnumerable source, int index, int indexFrom { Assert.Equal(expected, source.ElementAtOrDefault(index)); - if (index > 0) + if (index >= 0) { Assert.Equal(expected, source.ElementAtOrDefault(new Index(index))); } @@ -66,7 +66,7 @@ public void ElementAtOrDefaultRunOnce(IEnumerable source, int index, int in { Assert.Equal(expected, source.RunOnce().ElementAtOrDefault(index)); - if (index > 0) + if (index >= 0) { Assert.Equal(expected, source.RunOnce().ElementAtOrDefault(new Index(index))); } @@ -148,7 +148,6 @@ public void MutableSourceNotList() public void NonEmptySource_Consistency() { int?[] source = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; - int? @null = null; Assert.Equal(5, source.ElementAtOrDefault(5)); Assert.Equal(5, source.ElementAtOrDefault(new Index(5))); @@ -162,25 +161,24 @@ public void NonEmptySource_Consistency() Assert.Equal(9, source.ElementAtOrDefault(new Index(9))); Assert.Equal(9, source.ElementAtOrDefault(^1)); - Assert.Equal(@null, source.ElementAtOrDefault(-1)); - Assert.Equal(@null, source.ElementAtOrDefault(^11)); + Assert.Null(source.ElementAtOrDefault(-1)); + Assert.Null(source.ElementAtOrDefault(^11)); - Assert.Equal(@null, source.ElementAtOrDefault(10)); - Assert.Equal(@null, source.ElementAtOrDefault(new Index(10))); - Assert.Equal(@null, source.ElementAtOrDefault(^0)); + Assert.Null(source.ElementAtOrDefault(10)); + Assert.Null(source.ElementAtOrDefault(new Index(10))); + Assert.Null(source.ElementAtOrDefault(^0)); - Assert.Equal(@null, source.ElementAtOrDefault(int.MinValue)); - Assert.Equal(@null, source.ElementAtOrDefault(^int.MaxValue)); + Assert.Null(source.ElementAtOrDefault(int.MinValue)); + Assert.Null(source.ElementAtOrDefault(^int.MaxValue)); - Assert.Equal(@null, source.ElementAtOrDefault(int.MaxValue)); - Assert.Equal(@null, source.ElementAtOrDefault(new Index(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 }; - int? @null = null; Assert.Equal(5, ForceNotCollection(source).ElementAtOrDefault(5)); Assert.Equal(5, ForceNotCollection(source).ElementAtOrDefault(new Index(5))); @@ -194,25 +192,24 @@ public void NonEmptySource_Consistency_NotList() Assert.Equal(9, ForceNotCollection(source).ElementAtOrDefault(new Index(9))); Assert.Equal(9, ForceNotCollection(source).ElementAtOrDefault(^1)); - Assert.Equal(@null, ForceNotCollection(source).ElementAtOrDefault(-1)); - Assert.Equal(@null, ForceNotCollection(source).ElementAtOrDefault(^11)); + Assert.Null(ForceNotCollection(source).ElementAtOrDefault(-1)); + Assert.Null(ForceNotCollection(source).ElementAtOrDefault(^11)); - Assert.Equal(@null, ForceNotCollection(source).ElementAtOrDefault(10)); - Assert.Equal(@null, ForceNotCollection(source).ElementAtOrDefault(new Index(10))); - Assert.Equal(@null, ForceNotCollection(source).ElementAtOrDefault(^0)); + Assert.Null(ForceNotCollection(source).ElementAtOrDefault(10)); + Assert.Null(ForceNotCollection(source).ElementAtOrDefault(new Index(10))); + Assert.Null(ForceNotCollection(source).ElementAtOrDefault(^0)); - Assert.Equal(@null, ForceNotCollection(source).ElementAtOrDefault(int.MinValue)); - Assert.Equal(@null, ForceNotCollection(source).ElementAtOrDefault(^int.MaxValue)); + Assert.Null(ForceNotCollection(source).ElementAtOrDefault(int.MinValue)); + Assert.Null(ForceNotCollection(source).ElementAtOrDefault(^int.MaxValue)); - Assert.Equal(@null, ForceNotCollection(source).ElementAtOrDefault(int.MaxValue)); - Assert.Equal(@null, ForceNotCollection(source).ElementAtOrDefault(new Index(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 }; - int? @null = null; Assert.Equal(5, ListPartition(source).ElementAtOrDefault(5)); Assert.Equal(5, ListPartition(source).ElementAtOrDefault(new Index(5))); @@ -226,25 +223,24 @@ public void NonEmptySource_Consistency_ListPartition() Assert.Equal(9, ListPartition(source).ElementAtOrDefault(new Index(9))); Assert.Equal(9, ListPartition(source).ElementAtOrDefault(^1)); - Assert.Equal(@null, ListPartition(source).ElementAtOrDefault(-1)); - Assert.Equal(@null, ListPartition(source).ElementAtOrDefault(^11)); + Assert.Null(ListPartition(source).ElementAtOrDefault(-1)); + Assert.Null(ListPartition(source).ElementAtOrDefault(^11)); - Assert.Equal(@null, ListPartition(source).ElementAtOrDefault(10)); - Assert.Equal(@null, ListPartition(source).ElementAtOrDefault(new Index(10))); - Assert.Equal(@null, ListPartition(source).ElementAtOrDefault(^0)); + Assert.Null(ListPartition(source).ElementAtOrDefault(10)); + Assert.Null(ListPartition(source).ElementAtOrDefault(new Index(10))); + Assert.Null(ListPartition(source).ElementAtOrDefault(^0)); - Assert.Equal(@null, ListPartition(source).ElementAtOrDefault(int.MinValue)); - Assert.Equal(@null, ListPartition(source).ElementAtOrDefault(^int.MaxValue)); + Assert.Null(ListPartition(source).ElementAtOrDefault(int.MinValue)); + Assert.Null(ListPartition(source).ElementAtOrDefault(^int.MaxValue)); - Assert.Equal(@null, ListPartition(source).ElementAtOrDefault(int.MaxValue)); - Assert.Equal(@null, ListPartition(source).ElementAtOrDefault(new Index(int.MaxValue))); + Assert.Null(ListPartition(source).ElementAtOrDefault(int.MaxValue)); + Assert.Null(ListPartition(source).ElementAtOrDefault(new Index(int.MaxValue))); } [Fact] public void NonEmptySource_Consistency_EnumerablePartition() { int?[] source = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; - int? @null = null; Assert.Equal(5, EnumerablePartition(source).ElementAtOrDefault(5)); Assert.Equal(5, EnumerablePartition(source).ElementAtOrDefault(new Index(5))); @@ -258,106 +254,102 @@ public void NonEmptySource_Consistency_EnumerablePartition() Assert.Equal(9, EnumerablePartition(source).ElementAtOrDefault(new Index(9))); Assert.Equal(9, EnumerablePartition(source).ElementAtOrDefault(^1)); - Assert.Equal(@null, EnumerablePartition(source).ElementAtOrDefault(-1)); - Assert.Equal(@null, EnumerablePartition(source).ElementAtOrDefault(^11)); + Assert.Null(EnumerablePartition(source).ElementAtOrDefault(-1)); + Assert.Null(EnumerablePartition(source).ElementAtOrDefault(^11)); - Assert.Equal(@null, EnumerablePartition(source).ElementAtOrDefault(10)); - Assert.Equal(@null, EnumerablePartition(source).ElementAtOrDefault(new Index(10))); - Assert.Equal(@null, EnumerablePartition(source).ElementAtOrDefault(^0)); + Assert.Null(EnumerablePartition(source).ElementAtOrDefault(10)); + Assert.Null(EnumerablePartition(source).ElementAtOrDefault(new Index(10))); + Assert.Null(EnumerablePartition(source).ElementAtOrDefault(^0)); - Assert.Equal(@null, EnumerablePartition(source).ElementAtOrDefault(int.MinValue)); - Assert.Equal(@null, EnumerablePartition(source).ElementAtOrDefault(^int.MaxValue)); + Assert.Null(EnumerablePartition(source).ElementAtOrDefault(int.MinValue)); + Assert.Null(EnumerablePartition(source).ElementAtOrDefault(^int.MaxValue)); - Assert.Equal(@null, EnumerablePartition(source).ElementAtOrDefault(int.MaxValue)); - Assert.Equal(@null, EnumerablePartition(source).ElementAtOrDefault(new Index(int.MaxValue))); + Assert.Null(EnumerablePartition(source).ElementAtOrDefault(int.MaxValue)); + Assert.Null(EnumerablePartition(source).ElementAtOrDefault(new Index(int.MaxValue))); } [Fact] public void EmptySource_Consistency() { int?[] source = { }; - int? @null = null; - Assert.Equal(@null, source.ElementAtOrDefault(1)); - Assert.Equal(@null, source.ElementAtOrDefault(-1)); - Assert.Equal(@null, source.ElementAtOrDefault(new Index(1))); - Assert.Equal(@null, source.ElementAtOrDefault(^1)); + Assert.Null(source.ElementAtOrDefault(1)); + Assert.Null(source.ElementAtOrDefault(-1)); + Assert.Null(source.ElementAtOrDefault(new Index(1))); + Assert.Null(source.ElementAtOrDefault(^1)); - Assert.Equal(@null, source.ElementAtOrDefault(0)); - Assert.Equal(@null, source.ElementAtOrDefault(new Index(0))); - Assert.Equal(@null, source.ElementAtOrDefault(^0)); + Assert.Null(source.ElementAtOrDefault(0)); + Assert.Null(source.ElementAtOrDefault(new Index(0))); + Assert.Null(source.ElementAtOrDefault(^0)); - Assert.Equal(@null, source.ElementAtOrDefault(int.MinValue)); - Assert.Equal(@null, source.ElementAtOrDefault(^int.MaxValue)); + Assert.Null(source.ElementAtOrDefault(int.MinValue)); + Assert.Null(source.ElementAtOrDefault(^int.MaxValue)); - Assert.Equal(@null, source.ElementAtOrDefault(int.MaxValue)); - Assert.Equal(@null, source.ElementAtOrDefault(new Index(int.MaxValue))); + Assert.Null(source.ElementAtOrDefault(int.MaxValue)); + Assert.Null(source.ElementAtOrDefault(new Index(int.MaxValue))); } [Fact] public void EmptySource_Consistency_NotList() { int?[] source = { }; - int? @null = null; - Assert.Equal(@null, ForceNotCollection(source).ElementAtOrDefault(1)); - Assert.Equal(@null, ForceNotCollection(source).ElementAtOrDefault(-1)); - Assert.Equal(@null, ForceNotCollection(source).ElementAtOrDefault(new Index(1))); - Assert.Equal(@null, ForceNotCollection(source).ElementAtOrDefault(^1)); + 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.Equal(@null, ForceNotCollection(source).ElementAtOrDefault(0)); - Assert.Equal(@null, ForceNotCollection(source).ElementAtOrDefault(new Index(0))); - Assert.Equal(@null, ForceNotCollection(source).ElementAtOrDefault(^0)); + Assert.Null(ForceNotCollection(source).ElementAtOrDefault(0)); + Assert.Null(ForceNotCollection(source).ElementAtOrDefault(new Index(0))); + Assert.Null(ForceNotCollection(source).ElementAtOrDefault(^0)); - Assert.Equal(@null, ForceNotCollection(source).ElementAtOrDefault(int.MinValue)); - Assert.Equal(@null, ForceNotCollection(source).ElementAtOrDefault(^int.MaxValue)); + Assert.Null(ForceNotCollection(source).ElementAtOrDefault(int.MinValue)); + Assert.Null(ForceNotCollection(source).ElementAtOrDefault(^int.MaxValue)); - Assert.Equal(@null, ForceNotCollection(source).ElementAtOrDefault(int.MaxValue)); - Assert.Equal(@null, ForceNotCollection(source).ElementAtOrDefault(new Index(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 = { }; - int? @null = null; - Assert.Equal(@null, ListPartition(source).ElementAtOrDefault(1)); - Assert.Equal(@null, ListPartition(source).ElementAtOrDefault(-1)); - Assert.Equal(@null, ListPartition(source).ElementAtOrDefault(new Index(1))); - Assert.Equal(@null, ListPartition(source).ElementAtOrDefault(^1)); + Assert.Null(ListPartition(source).ElementAtOrDefault(1)); + Assert.Null(ListPartition(source).ElementAtOrDefault(-1)); + Assert.Null(ListPartition(source).ElementAtOrDefault(new Index(1))); + Assert.Null(ListPartition(source).ElementAtOrDefault(^1)); - Assert.Equal(@null, ListPartition(source).ElementAtOrDefault(0)); - Assert.Equal(@null, ListPartition(source).ElementAtOrDefault(new Index(0))); - Assert.Equal(@null, ListPartition(source).ElementAtOrDefault(^0)); + Assert.Null(ListPartition(source).ElementAtOrDefault(0)); + Assert.Null(ListPartition(source).ElementAtOrDefault(new Index(0))); + Assert.Null(ListPartition(source).ElementAtOrDefault(^0)); - Assert.Equal(@null, ListPartition(source).ElementAtOrDefault(int.MinValue)); - Assert.Equal(@null, ListPartition(source).ElementAtOrDefault(^int.MaxValue)); + Assert.Null(ListPartition(source).ElementAtOrDefault(int.MinValue)); + Assert.Null(ListPartition(source).ElementAtOrDefault(^int.MaxValue)); - Assert.Equal(@null, ListPartition(source).ElementAtOrDefault(int.MaxValue)); - Assert.Equal(@null, ListPartition(source).ElementAtOrDefault(new Index(int.MaxValue))); + Assert.Null(ListPartition(source).ElementAtOrDefault(int.MaxValue)); + Assert.Null(ListPartition(source).ElementAtOrDefault(new Index(int.MaxValue))); } [Fact] public void EmptySource_Consistency_EnumerablePartition() { int?[] source = { }; - int? @null = null; - Assert.Equal(@null, EnumerablePartition(source).ElementAtOrDefault(1)); - Assert.Equal(@null, EnumerablePartition(source).ElementAtOrDefault(-1)); - Assert.Equal(@null, EnumerablePartition(source).ElementAtOrDefault(new Index(1))); - Assert.Equal(@null, EnumerablePartition(source).ElementAtOrDefault(^1)); + Assert.Null(EnumerablePartition(source).ElementAtOrDefault(1)); + Assert.Null(EnumerablePartition(source).ElementAtOrDefault(-1)); + Assert.Null(EnumerablePartition(source).ElementAtOrDefault(new Index(1))); + Assert.Null(EnumerablePartition(source).ElementAtOrDefault(^1)); - Assert.Equal(@null, EnumerablePartition(source).ElementAtOrDefault(0)); - Assert.Equal(@null, EnumerablePartition(source).ElementAtOrDefault(new Index(0))); - Assert.Equal(@null, EnumerablePartition(source).ElementAtOrDefault(^0)); + Assert.Null(EnumerablePartition(source).ElementAtOrDefault(0)); + Assert.Null(EnumerablePartition(source).ElementAtOrDefault(new Index(0))); + Assert.Null(EnumerablePartition(source).ElementAtOrDefault(^0)); - Assert.Equal(@null, EnumerablePartition(source).ElementAtOrDefault(int.MinValue)); - Assert.Equal(@null, EnumerablePartition(source).ElementAtOrDefault(^int.MaxValue)); + Assert.Null(EnumerablePartition(source).ElementAtOrDefault(int.MinValue)); + Assert.Null(EnumerablePartition(source).ElementAtOrDefault(^int.MaxValue)); - Assert.Equal(@null, EnumerablePartition(source).ElementAtOrDefault(int.MaxValue)); - Assert.Equal(@null, EnumerablePartition(source).ElementAtOrDefault(new Index(int.MaxValue))); + Assert.Null(EnumerablePartition(source).ElementAtOrDefault(int.MaxValue)); + Assert.Null(EnumerablePartition(source).ElementAtOrDefault(new Index(int.MaxValue))); } } } diff --git a/src/libraries/System.Linq/tests/TakeTests.cs b/src/libraries/System.Linq/tests/TakeTests.cs index c98944b24b5581..a444b77e565158 100644 --- a/src/libraries/System.Linq/tests/TakeTests.cs +++ b/src/libraries/System.Linq/tests/TakeTests.cs @@ -71,185 +71,185 @@ public void SameResultsRepeatCallsStringQueryIList() [Fact] public void SourceEmptyCountPositive() { - int[] source = { }; - Assert.Empty(source.Take(5)); + var source = Repeat(_ => new int[] { }, 5); + Assert.Empty(source[0].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)); + Assert.Empty(source[1].Take(0..5)); + Assert.Empty(source[2].Take(^5..5)); + Assert.Empty(source[3].Take(0..^0)); + Assert.Empty(source[4].Take(^5..^0)); } [Fact] public void SourceEmptyCountPositiveNotIList() { - var source = NumberRangeGuaranteedNotCollectionType(0, 0); - Assert.Empty(source.Take(5)); + var source = Repeat(_ => NumberRangeGuaranteedNotCollectionType(0, 0), 5); + Assert.Empty(source[0].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)); + Assert.Empty(source[1].Take(0..5)); + Assert.Empty(source[2].Take(^5..5)); + Assert.Empty(source[3].Take(0..^0)); + Assert.Empty(source[4].Take(^5..^0)); } [Fact] public void SourceNonEmptyCountNegative() { - int[] source = { 2, 5, 9, 1 }; - Assert.Empty(source.Take(-5)); + var source = Repeat(_ => new[] { 2, 5, 9, 1 }, 2); + Assert.Empty(source[0].Take(-5)); - Assert.Empty(source.Take(^9..0)); + Assert.Empty(source[1].Take(^9..0)); } [Fact] public void SourceNonEmptyCountNegativeNotIList() { - var source = ForceNotCollection(new[] { 2, 5, 9, 1 }); - Assert.Empty(source.Take(-5)); + var source = Repeat(_ => ForceNotCollection(new[] { 2, 5, 9, 1 }), 2); + Assert.Empty(source[0].Take(-5)); - Assert.Empty(source.Take(^9..0)); + Assert.Empty(source[1].Take(^9..0)); } [Fact] public void SourceNonEmptyCountZero() { - int[] source = { 2, 5, 9, 1 }; - Assert.Empty(source.Take(0)); + var source = Repeat(_ => new[] { 2, 5, 9, 1 }, 5); + Assert.Empty(source[0].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)); + Assert.Empty(source[1].Take(0..0)); + Assert.Empty(source[2].Take(^4..0)); + Assert.Empty(source[3].Take(0..^4)); + Assert.Empty(source[4].Take(^4..^4)); } [Fact] public void SourceNonEmptyCountZeroNotIList() { - var source = ForceNotCollection(new[] { 2, 5, 9, 1 }); - Assert.Empty(source.Take(0)); + var source = Repeat(_ => ForceNotCollection(new[] { 2, 5, 9, 1 }), 5); + Assert.Empty(source[0].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)); + Assert.Empty(source[1].Take(0..0)); + Assert.Empty(source[2].Take(^4..0)); + Assert.Empty(source[3].Take(0..^4)); + Assert.Empty(source[4].Take(^4..^4)); } [Fact] public void SourceNonEmptyCountOne() { - int[] source = { 2, 5, 9, 1 }; + var source = Repeat(_ => new[] { 2, 5, 9, 1 }, 5); int[] expected = { 2 }; - Assert.Equal(expected, source.Take(1)); + Assert.Equal(expected, source[0].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)); + Assert.Equal(expected, source[1].Take(0..1)); + Assert.Equal(expected, source[2].Take(^4..1)); + Assert.Equal(expected, source[3].Take(0..^3)); + Assert.Equal(expected, source[4].Take(^4..^3)); } [Fact] public void SourceNonEmptyCountOneNotIList() { - var source = ForceNotCollection(new[] { 2, 5, 9, 1 }); + var source = Repeat(_ => ForceNotCollection(new[] { 2, 5, 9, 1 }), 5); int[] expected = { 2 }; - Assert.Equal(expected, source.Take(1)); + Assert.Equal(expected, source[0].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)); + Assert.Equal(expected, source[1].Take(0..1)); + Assert.Equal(expected, source[2].Take(^4..1)); + Assert.Equal(expected, source[3].Take(0..^3)); + Assert.Equal(expected, source[4].Take(^4..^3)); } [Fact] public void SourceNonEmptyTakeAllExactly() { - int[] source = { 2, 5, 9, 1 }; + var source = Repeat(_ => new[] { 2, 5, 9, 1 }, 5); - Assert.Equal(source, source.Take(source.Length)); + Assert.Equal(source[0], source[0].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)); + Assert.Equal(source[1], source[1].Take(0..source.Length)); + Assert.Equal(source[2], source[2].Take(^source.Length..source.Length)); + Assert.Equal(source[3], source[3].Take(0..^0)); + Assert.Equal(source[4], source[4].Take(^source.Length..^0)); } [Fact] public void SourceNonEmptyTakeAllExactlyNotIList() { - var source = ForceNotCollection(new[] { 2, 5, 9, 1 }); + var source = Repeat(_ => ForceNotCollection(new[] { 2, 5, 9, 1 }), 5); - Assert.Equal(source, source.Take(source.Count())); + Assert.Equal(source[0], source[0].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)); + Assert.Equal(source[1], source[1].Take(0..source[1].Count())); + Assert.Equal(source[2], source[2].Take(^source[2].Count()..source[2].Count())); + Assert.Equal(source[3], source[3].Take(0..^0)); + Assert.Equal(source[4], source[4].Take(^source[4].Count()..^0)); } [Fact] public void SourceNonEmptyTakeAllButOne() { - int[] source = { 2, 5, 9, 1 }; + var source = Repeat(_ => new[] { 2, 5, 9, 1 }, 5); int[] expected = { 2, 5, 9 }; - Assert.Equal(expected, source.Take(3)); + Assert.Equal(expected, source[0].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)); + Assert.Equal(expected, source[1].Take(0..3)); + Assert.Equal(expected, source[2].Take(^4..3)); + Assert.Equal(expected, source[3].Take(0..^1)); + Assert.Equal(expected, source[4].Take(^4..^1)); } [Fact] public void RunOnce() { - int[] source = { 2, 5, 9, 1 }; + var source = Repeat(_ => new[] { 2, 5, 9, 1 }, 5); int[] expected = { 2, 5, 9 }; - Assert.Equal(expected, source.RunOnce().Take(3)); + Assert.Equal(expected, source[0].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)); + Assert.Equal(expected, source[1].RunOnce().Take(0..3)); + Assert.Equal(expected, source[2].RunOnce().Take(^4..3)); + Assert.Equal(expected, source[3].RunOnce().Take(0..^1)); + Assert.Equal(expected, source[4].RunOnce().Take(^4..^1)); } [Fact] public void SourceNonEmptyTakeAllButOneNotIList() { - var source = ForceNotCollection(new[] { 2, 5, 9, 1 }); + var source = Repeat(_ => ForceNotCollection(new[] { 2, 5, 9, 1 }), 5); int[] expected = { 2, 5, 9 }; - Assert.Equal(expected, source.Take(3)); + Assert.Equal(expected, source[0].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)); + Assert.Equal(expected, source[1].RunOnce().Take(0..3)); + Assert.Equal(expected, source[2].RunOnce().Take(^4..3)); + Assert.Equal(expected, source[3].RunOnce().Take(0..^1)); + Assert.Equal(expected, source[4].RunOnce().Take(^4..^1)); } [Fact] public void SourceNonEmptyTakeExcessive() { - int?[] source = { 2, 5, null, 9, 1 }; + var source = Repeat(_ => new int?[] { 2, 5, null, 9, 1 }, 3); - Assert.Equal(source, source.Take(source.Length + 1)); + Assert.Equal(source[0], source[0].Take(source[0].Length + 1)); - Assert.Equal(source, source.Take(0..(source.Length + 1))); - Assert.Equal(source, source.Take(^(source.Length + 1)..(source.Length + 1))); + Assert.Equal(source[1], source[1].Take(0..(source[1].Length + 1))); + Assert.Equal(source[2], source[2].Take(^(source[2].Length + 1)..(source[2].Length + 1))); } [Fact] public void SourceNonEmptyTakeExcessiveNotIList() { - var source = ForceNotCollection(new int?[] { 2, 5, null, 9, 1 }); + var source = Repeat(_ => ForceNotCollection(new int?[] { 2, 5, null, 9, 1 }), 3); - Assert.Equal(source, source.Take(source.Count() + 1)); + Assert.Equal(source[0], source[0].Take(source[0].Count() + 1)); - Assert.Equal(source, source.Take(0..(source.Count() + 1))); - Assert.Equal(source, source.Take(^(source.Count() + 1)..(source.Count() + 1))); + Assert.Equal(source[1], source[1].Take(0..(source[1].Count() + 1))); + Assert.Equal(source[2], source[2].Take(^(source[2].Count() + 1)..(source[2].Count() + 1))); } [Fact] @@ -318,695 +318,707 @@ public void ForcedToEnumeratorDoesntEnumerateIList() [Fact] public void FollowWithTake() { - var source = new[] { 5, 6, 7, 8 }; + var source = Repeat(_ => new[] { 5, 6, 7, 8 }, 5); var expected = new[] { 5, 6 }; - Assert.Equal(expected, source.Take(5).Take(3).Take(2).Take(40)); + Assert.Equal(expected, source[0].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)); + Assert.Equal(expected, source[1].Take(0..5).Take(0..3).Take(0..2).Take(0..40)); + Assert.Equal(expected, source[2].Take(^4..5).Take(^4..3).Take(^3..2).Take(^2..40)); + Assert.Equal(expected, source[3].Take(0..^0).Take(0..^1).Take(0..^1).Take(0..^0)); + Assert.Equal(expected, source[4].Take(^4..^0).Take(^4..^1).Take(^3..^1).Take(^2..^0)); } [Fact] public void FollowWithTakeNotIList() { - var source = NumberRangeGuaranteedNotCollectionType(5, 4); + var source = Repeat(_ => NumberRangeGuaranteedNotCollectionType(5, 4), 5); var expected = new[] { 5, 6 }; - Assert.Equal(expected, source.Take(5).Take(3).Take(2)); + Assert.Equal(expected, source[0].Take(5).Take(3).Take(2)); - 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)); + Assert.Equal(expected, source[1].Take(0..5).Take(0..3).Take(0..2)); + Assert.Equal(expected, source[2].Take(^4..5).Take(^4..3).Take(^3..2)); + Assert.Equal(expected, source[3].Take(0..^0).Take(0..^1).Take(0..^1)); + Assert.Equal(expected, source[4].Take(^4..^0).Take(^4..^1).Take(^3..^1)); } [Fact] public void FollowWithSkip() { - var source = new[] { 1, 2, 3, 4, 5, 6 }; + var source = Repeat(_ => new[] { 1, 2, 3, 4, 5, 6 }, 5); var expected = new[] { 3, 4, 5 }; - Assert.Equal(expected, source.Take(5).Skip(2).Skip(-4)); + Assert.Equal(expected, source[0].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)); + Assert.Equal(expected, source[1].Take(0..5).Skip(2).Skip(-4)); + Assert.Equal(expected, source[2].Take(^6..5).Skip(2).Skip(-4)); + Assert.Equal(expected, source[3].Take(0..^1).Skip(2).Skip(-4)); + Assert.Equal(expected, source[4].Take(^6..^1).Skip(2).Skip(-4)); } [Fact] public void FollowWithSkipNotIList() { - var source = NumberRangeGuaranteedNotCollectionType(1, 6); + var source = Repeat(_ => NumberRangeGuaranteedNotCollectionType(1, 6), 5); var expected = new[] { 3, 4, 5 }; - Assert.Equal(expected, source.Take(5).Skip(2).Skip(-4)); + Assert.Equal(expected, source[0].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)); + Assert.Equal(expected, source[1].Take(0..5).Skip(2).Skip(-4)); + Assert.Equal(expected, source[2].Take(^6..5).Skip(2).Skip(-4)); + Assert.Equal(expected, source[3].Take(0..^1).Skip(2).Skip(-4)); + Assert.Equal(expected, source[4].Take(^6..^1).Skip(2).Skip(-4)); } [Fact] public void ElementAt() { - var source = new[] { 1, 2, 3, 4, 5, 6 }; - var taken1 = source.Take(3); + var source = Repeat(_ => new[] { 1, 2, 3, 4, 5, 6 }, 5); + var taken0 = source[0].Take(3); + Assert.Equal(1, taken0.ElementAt(0)); + Assert.Equal(3, taken0.ElementAt(2)); + AssertExtensions.Throws("index", () => taken0.ElementAt(-1)); + AssertExtensions.Throws("index", () => taken0.ElementAt(3)); + + var taken1 = source[1].Take(0..3); Assert.Equal(1, taken1.ElementAt(0)); Assert.Equal(3, taken1.ElementAt(2)); AssertExtensions.Throws("index", () => taken1.ElementAt(-1)); AssertExtensions.Throws("index", () => taken1.ElementAt(3)); - var taken2 = source.Take(0..3); + var taken2 = source[2].Take(^6..3); Assert.Equal(1, taken2.ElementAt(0)); Assert.Equal(3, taken2.ElementAt(2)); AssertExtensions.Throws("index", () => taken2.ElementAt(-1)); AssertExtensions.Throws("index", () => taken2.ElementAt(3)); - var taken3 = source.Take(^6..3); + var taken3 = source[3].Take(0..^3); Assert.Equal(1, taken3.ElementAt(0)); Assert.Equal(3, taken3.ElementAt(2)); AssertExtensions.Throws("index", () => taken3.ElementAt(-1)); AssertExtensions.Throws("index", () => taken3.ElementAt(3)); - var taken4 = source.Take(0..^3); + var taken4 = source[4].Take(^6..^3); Assert.Equal(1, taken4.ElementAt(0)); Assert.Equal(3, taken4.ElementAt(2)); AssertExtensions.Throws("index", () => taken4.ElementAt(-1)); AssertExtensions.Throws("index", () => taken4.ElementAt(3)); - - var taken5 = source.Take(^6..^3); - Assert.Equal(1, taken5.ElementAt(0)); - Assert.Equal(3, taken5.ElementAt(2)); - AssertExtensions.Throws("index", () => taken5.ElementAt(-1)); - AssertExtensions.Throws("index", () => taken5.ElementAt(3)); } [Fact] public void ElementAtNotIList() { - var source = ForceNotCollection(new[] { 1, 2, 3, 4, 5, 6 }); - var taken1 = source.Take(3); + var source = Repeat(_ => ForceNotCollection(new[] { 1, 2, 3, 4, 5, 6 }), 5); + var taken0 = source[0].Take(3); + Assert.Equal(1, taken0.ElementAt(0)); + Assert.Equal(3, taken0.ElementAt(2)); + AssertExtensions.Throws("index", () => taken0.ElementAt(-1)); + AssertExtensions.Throws("index", () => taken0.ElementAt(3)); + + var taken1 = source[1].Take(0..3); Assert.Equal(1, taken1.ElementAt(0)); Assert.Equal(3, taken1.ElementAt(2)); AssertExtensions.Throws("index", () => taken1.ElementAt(-1)); AssertExtensions.Throws("index", () => taken1.ElementAt(3)); - var taken2 = source.Take(0..3); + var taken2 = source[2].Take(^6..3); Assert.Equal(1, taken2.ElementAt(0)); Assert.Equal(3, taken2.ElementAt(2)); AssertExtensions.Throws("index", () => taken2.ElementAt(-1)); AssertExtensions.Throws("index", () => taken2.ElementAt(3)); - var taken3 = source.Take(^6..3); + var taken3 = source[3].Take(0..^3); Assert.Equal(1, taken3.ElementAt(0)); Assert.Equal(3, taken3.ElementAt(2)); AssertExtensions.Throws("index", () => taken3.ElementAt(-1)); AssertExtensions.Throws("index", () => taken3.ElementAt(3)); - var taken4 = source.Take(0..^3); + var taken4 = source[4].Take(^6..^3); Assert.Equal(1, taken4.ElementAt(0)); Assert.Equal(3, taken4.ElementAt(2)); AssertExtensions.Throws("index", () => taken4.ElementAt(-1)); AssertExtensions.Throws("index", () => taken4.ElementAt(3)); - - var taken5 = source.Take(^6..^3); - Assert.Equal(1, taken5.ElementAt(0)); - Assert.Equal(3, taken5.ElementAt(2)); - AssertExtensions.Throws("index", () => taken5.ElementAt(-1)); - AssertExtensions.Throws("index", () => taken5.ElementAt(3)); } [Fact] public void ElementAtOrDefault() { - var source = new[] { 1, 2, 3, 4, 5, 6 }; - var taken1 = source.Take(3); + var source = Repeat(_ => new[] { 1, 2, 3, 4, 5, 6 }, 5); + var taken0 = source[0].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[1].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(0..3); + var taken2 = source[2].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(^6..3); + var taken3 = source[3].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(0..^3); + var taken4 = source[4].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)); - - var taken5 = source.Take(^6..^3); - Assert.Equal(1, taken5.ElementAtOrDefault(0)); - Assert.Equal(3, taken5.ElementAtOrDefault(2)); - Assert.Equal(0, taken5.ElementAtOrDefault(-1)); - Assert.Equal(0, taken5.ElementAtOrDefault(3)); } [Fact] public void ElementAtOrDefaultNotIList() { - var source = ForceNotCollection(new[] { 1, 2, 3, 4, 5, 6 }); - var taken1 = source.Take(3); + var source = Repeat(_ => ForceNotCollection(new[] { 1, 2, 3, 4, 5, 6 }), 5); + var taken0 = source[0].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[1].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(0..3); + var taken2 = source[2].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(^6..3); + var taken3 = source[3].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(0..^3); + var taken4 = source[4].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)); - - var taken5 = source.Take(^6..^3); - Assert.Equal(1, taken5.ElementAtOrDefault(0)); - Assert.Equal(3, taken5.ElementAtOrDefault(2)); - Assert.Equal(0, taken5.ElementAtOrDefault(-1)); - Assert.Equal(0, taken5.ElementAtOrDefault(3)); } [Fact] public void First() { - var source = 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()); + var source = Repeat(_ => new[] { 1, 2, 3, 4, 5 }, 5); + Assert.Equal(1, source[0].Take(1).First()); + Assert.Equal(1, source[0].Take(4).First()); + Assert.Equal(1, source[0].Take(40).First()); + Assert.Throws(() => source[0].Take(0).First()); + Assert.Throws(() => source[0].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[1].Take(0..1).First()); + Assert.Equal(1, source[1].Take(0..4).First()); + Assert.Equal(1, source[1].Take(0..40).First()); + Assert.Throws(() => source[1].Take(0..0).First()); + Assert.Throws(() => source[1].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[2].Take(^5..1).First()); + Assert.Equal(1, source[2].Take(^5..4).First()); + Assert.Equal(1, source[2].Take(^5..40).First()); + Assert.Throws(() => source[2].Take(^5..0).First()); + Assert.Throws(() => source[2].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(^10..^5).First()); + Assert.Equal(1, source[3].Take(0..^4).First()); + Assert.Equal(1, source[3].Take(0..^1).First()); + Assert.Equal(1, source[3].Take(0..^0).First()); + Assert.Throws(() => source[3].Take(0..^5).First()); + Assert.Throws(() => source[3].Skip(5).Take(0..^5).First()); + + Assert.Equal(1, source[4].Take(^5..^4).First()); + Assert.Equal(1, source[4].Take(^5..^1).First()); + Assert.Equal(1, source[4].Take(^5..^0).First()); + Assert.Throws(() => source[4].Take(^5..^5).First()); + Assert.Throws(() => source[4].Skip(5).Take(^10..^0).First()); } [Fact] public void FirstNotIList() { - 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()); + var source = Repeat(_ => ForceNotCollection(new[] { 1, 2, 3, 4, 5 }), 5); + Assert.Equal(1, source[0].Take(1).First()); + Assert.Equal(1, source[0].Take(4).First()); + Assert.Equal(1, source[0].Take(40).First()); + Assert.Throws(() => source[0].Take(0).First()); + Assert.Throws(() => source[0].Skip(5).Take(10).First()); + + Assert.Equal(1, source[1].Take(0..1).First()); + Assert.Equal(1, source[1].Take(0..4).First()); + Assert.Equal(1, source[1].Take(0..40).First()); + Assert.Throws(() => source[1].Take(0..0).First()); + Assert.Throws(() => source[1].Skip(5).Take(0..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[2].Take(^5..1).First()); + Assert.Equal(1, source[2].Take(^5..4).First()); + Assert.Equal(1, source[2].Take(^5..40).First()); + Assert.Throws(() => source[2].Take(^5..0).First()); + Assert.Throws(() => source[2].Skip(5).Take(^5..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[3].Take(0..^4).First()); + Assert.Equal(1, source[3].Take(0..^1).First()); + Assert.Equal(1, source[3].Take(0..^0).First()); + Assert.Throws(() => source[3].Take(0..^5).First()); + Assert.Throws(() => source[3].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()); + Assert.Equal(1, source[4].Take(^5..^4).First()); + Assert.Equal(1, source[4].Take(^5..^1).First()); + Assert.Equal(1, source[4].Take(^5..^0).First()); + Assert.Throws(() => source[4].Take(^5..^5).First()); + Assert.Throws(() => source[4].Skip(5).Take(^10..^0).First()); } [Fact] public void FirstOrDefault() { - var source = 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()); + var source = Repeat(_ => new[] { 1, 2, 3, 4, 5 }, 5); + Assert.Equal(1, source[0].Take(1).FirstOrDefault()); + Assert.Equal(1, source[0].Take(4).FirstOrDefault()); + Assert.Equal(1, source[0].Take(40).FirstOrDefault()); + Assert.Equal(0, source[0].Take(0).FirstOrDefault()); + Assert.Equal(0, source[0].Skip(5).Take(10).FirstOrDefault()); + + Assert.Equal(1, source[1].Take(0..1).FirstOrDefault()); + Assert.Equal(1, source[1].Take(0..4).FirstOrDefault()); + Assert.Equal(1, source[1].Take(0..40).FirstOrDefault()); + Assert.Equal(0, source[1].Take(0..0).FirstOrDefault()); + Assert.Equal(0, source[1].Skip(5).Take(0..10).FirstOrDefault()); + + Assert.Equal(1, source[2].Take(^5..1).FirstOrDefault()); + Assert.Equal(1, source[2].Take(^5..4).FirstOrDefault()); + Assert.Equal(1, source[2].Take(^5..40).FirstOrDefault()); + Assert.Equal(0, source[2].Take(^5..0).FirstOrDefault()); + Assert.Equal(0, source[2].Skip(5).Take(^10..10).FirstOrDefault()); + + Assert.Equal(1, source[3].Take(0..^4).FirstOrDefault()); + Assert.Equal(1, source[3].Take(0..^1).FirstOrDefault()); + Assert.Equal(1, source[3].Take(0..^0).FirstOrDefault()); + Assert.Equal(0, source[3].Take(0..^5).FirstOrDefault()); + Assert.Equal(0, source[3].Skip(5).Take(0..^10).FirstOrDefault()); + + Assert.Equal(1, source[4].Take(^5..^4).FirstOrDefault()); + Assert.Equal(1, source[4].Take(^5..^1).FirstOrDefault()); + Assert.Equal(1, source[4].Take(^5..^0).FirstOrDefault()); + Assert.Equal(0, source[4].Take(^5..^5).FirstOrDefault()); + Assert.Equal(0, source[4].Skip(5).Take(^10..^0).FirstOrDefault()); } [Fact] public void FirstOrDefaultNotIList() { - 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()); + var source = Repeat(_ => ForceNotCollection(new[] { 1, 2, 3, 4, 5 }), 5); + Assert.Equal(1, source[0].Take(1).FirstOrDefault()); + Assert.Equal(1, source[0].Take(4).FirstOrDefault()); + Assert.Equal(1, source[0].Take(40).FirstOrDefault()); + Assert.Equal(0, source[0].Take(0).FirstOrDefault()); + Assert.Equal(0, source[0].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[1].Take(0..1).FirstOrDefault()); + Assert.Equal(1, source[1].Take(0..4).FirstOrDefault()); + Assert.Equal(1, source[1].Take(0..40).FirstOrDefault()); + Assert.Equal(0, source[1].Take(0..0).FirstOrDefault()); + Assert.Equal(0, source[1].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[2].Take(^5..1).FirstOrDefault()); + Assert.Equal(1, source[2].Take(^5..4).FirstOrDefault()); + Assert.Equal(1, source[2].Take(^5..40).FirstOrDefault()); + Assert.Equal(0, source[2].Take(^5..0).FirstOrDefault()); + Assert.Equal(0, source[2].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[3].Take(0..^4).FirstOrDefault()); + Assert.Equal(1, source[3].Take(0..^1).FirstOrDefault()); + Assert.Equal(1, source[3].Take(0..^0).FirstOrDefault()); + Assert.Equal(0, source[3].Take(0..^5).FirstOrDefault()); + Assert.Equal(0, source[3].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()); + Assert.Equal(1, source[4].Take(^5..^4).FirstOrDefault()); + Assert.Equal(1, source[4].Take(^5..^1).FirstOrDefault()); + Assert.Equal(1, source[4].Take(^5..^0).FirstOrDefault()); + Assert.Equal(0, source[4].Take(^5..^5).FirstOrDefault()); + Assert.Equal(0, source[4].Skip(5).Take(^10..^0).FirstOrDefault()); } [Fact] public void Last() { - var source = 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()); + var source = Repeat(_ => new[] { 1, 2, 3, 4, 5 }, 5); + Assert.Equal(1, source[0].Take(1).Last()); + Assert.Equal(5, source[0].Take(5).Last()); + Assert.Equal(5, source[0].Take(40).Last()); + Assert.Throws(() => source[0].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.Equal(1, source[1].Take(0..1).Last()); + Assert.Equal(5, source[1].Take(0..5).Last()); + Assert.Equal(5, source[1].Take(0..40).Last()); + Assert.Throws(() => source[1].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.Equal(1, source[2].Take(^5..1).Last()); + Assert.Equal(5, source[2].Take(^5..5).Last()); + Assert.Equal(5, source[2].Take(^5..40).Last()); + Assert.Throws(() => source[2].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.Equal(1, source[3].Take(0..^4).Last()); + Assert.Equal(5, source[3].Take(0..^0).Last()); + Assert.Equal(5, source[3].Take(3..^0).Last()); + Assert.Throws(() => source[3].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.Equal(1, source[4].Take(^5..^4).Last()); + Assert.Equal(5, source[4].Take(^5..^0).Last()); + Assert.Equal(5, source[4].Take(^5..^0).Last()); + Assert.Throws(() => source[4].Take(^5..^5).Last()); Assert.Throws(() => Array.Empty().Take(^40..^0).Last()); } [Fact] public void LastNotIList() { - 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()); + var source = Repeat(_ => ForceNotCollection(new[] { 1, 2, 3, 4, 5 }), 5); + Assert.Equal(1, source[0].Take(1).Last()); + Assert.Equal(5, source[0].Take(5).Last()); + Assert.Equal(5, source[0].Take(40).Last()); + Assert.Throws(() => source[0].Take(0).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.Equal(1, source[1].Take(0..1).Last()); + Assert.Equal(5, source[1].Take(0..5).Last()); + Assert.Equal(5, source[1].Take(0..40).Last()); + Assert.Throws(() => source[1].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.Equal(1, source[2].Take(^5..1).Last()); + Assert.Equal(5, source[2].Take(^5..5).Last()); + Assert.Equal(5, source[2].Take(^5..40).Last()); + Assert.Throws(() => source[2].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.Equal(1, source[3].Take(0..^4).Last()); + Assert.Equal(5, source[3].Take(0..^0).Last()); + Assert.Equal(5, source[3].Take(3..^0).Last()); + Assert.Throws(() => source[3].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.Equal(1, source[4].Take(^5..^4).Last()); + Assert.Equal(5, source[4].Take(^5..^0).Last()); + Assert.Equal(5, source[4].Take(^5..^0).Last()); + Assert.Throws(() => source[4].Take(^5..^5).Last()); Assert.Throws(() => ForceNotCollection(Array.Empty()).Take(^40..^0).Last()); } [Fact] public void LastOrDefault() { - var source = 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()); + var source = Repeat(_ => new[] { 1, 2, 3, 4, 5 }, 5); + Assert.Equal(1, source[0].Take(1).LastOrDefault()); + Assert.Equal(5, source[0].Take(5).LastOrDefault()); + Assert.Equal(5, source[0].Take(40).LastOrDefault()); + Assert.Equal(0, source[0].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(1, source[1].Take(0..1).LastOrDefault()); + Assert.Equal(5, source[1].Take(0..5).LastOrDefault()); + Assert.Equal(5, source[1].Take(0..40).LastOrDefault()); + Assert.Equal(0, source[1].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(1, source[2].Take(^5..1).LastOrDefault()); + Assert.Equal(5, source[2].Take(^5..5).LastOrDefault()); + Assert.Equal(5, source[2].Take(^5..40).LastOrDefault()); + Assert.Equal(0, source[2].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(1, source[3].Take(0..^4).LastOrDefault()); + Assert.Equal(5, source[3].Take(0..^0).LastOrDefault()); + Assert.Equal(5, source[3].Take(3..^0).LastOrDefault()); + Assert.Equal(0, source[3].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(1, source[4].Take(^5..^4).LastOrDefault()); + Assert.Equal(5, source[4].Take(^5..^0).LastOrDefault()); + Assert.Equal(5, source[4].Take(^40..^0).LastOrDefault()); + Assert.Equal(0, source[4].Take(^5..^5).LastOrDefault()); Assert.Equal(0, Array.Empty().Take(^40..^0).LastOrDefault()); } [Fact] public void LastOrDefaultNotIList() { - 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()); + var source = Repeat(_ => ForceNotCollection(new[] { 1, 2, 3, 4, 5 }), 5); + Assert.Equal(1, source[0].Take(1).LastOrDefault()); + Assert.Equal(5, source[0].Take(5).LastOrDefault()); + Assert.Equal(5, source[0].Take(40).LastOrDefault()); + Assert.Equal(0, source[0].Take(0).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(1, source[1].Take(0..1).LastOrDefault()); + Assert.Equal(5, source[1].Take(0..5).LastOrDefault()); + Assert.Equal(5, source[1].Take(0..40).LastOrDefault()); + Assert.Equal(0, source[1].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(1, source[2].Take(^5..1).LastOrDefault()); + Assert.Equal(5, source[2].Take(^5..5).LastOrDefault()); + Assert.Equal(5, source[2].Take(^5..40).LastOrDefault()); + Assert.Equal(0, source[2].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(1, source[3].Take(0..^4).LastOrDefault()); + Assert.Equal(5, source[3].Take(0..^0).LastOrDefault()); + Assert.Equal(5, source[3].Take(3..^0).LastOrDefault()); + Assert.Equal(0, source[3].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(1, source[4].Take(^5..^4).LastOrDefault()); + Assert.Equal(5, source[4].Take(^5..^0).LastOrDefault()); + Assert.Equal(5, source[4].Take(^40..^0).LastOrDefault()); + Assert.Equal(0, source[4].Take(^5..^5).LastOrDefault()); Assert.Equal(0, ForceNotCollection(Array.Empty()).Take(^40..^0).LastOrDefault()); } [Fact] public void ToArray() { - var source = 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()); - Assert.Equal(new[] { 1, 2, 3, 4 }, source.Take(4).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()); + var source = Repeat(_ => new[] { 1, 2, 3, 4, 5 }, 5); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[0].Take(5).ToArray()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[0].Take(6).ToArray()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[0].Take(40).ToArray()); + Assert.Equal(new[] { 1, 2, 3, 4 }, source[0].Take(4).ToArray()); + Assert.Equal(1, source[0].Take(1).ToArray().Single()); + Assert.Empty(source[0].Take(0).ToArray()); + Assert.Empty(source[0].Take(-10).ToArray()); + + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[1].Take(0..5).ToArray()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[1].Take(0..6).ToArray()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[1].Take(0..40).ToArray()); + Assert.Equal(new[] { 1, 2, 3, 4 }, source[1].Take(0..4).ToArray()); + Assert.Equal(1, source[1].Take(0..1).ToArray().Single()); + Assert.Empty(source[1].Take(0..0).ToArray()); + + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[2].Take(^5..5).ToArray()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[2].Take(^5..6).ToArray()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[2].Take(^5..40).ToArray()); + Assert.Equal(new[] { 1, 2, 3, 4 }, source[2].Take(^5..4).ToArray()); + Assert.Equal(1, source[2].Take(^5..1).ToArray().Single()); + Assert.Empty(source[2].Take(^5..0).ToArray()); + Assert.Empty(source[2].Take(^15..0).ToArray()); + + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[3].Take(0..^0).ToArray()); + Assert.Equal(new[] { 1, 2, 3, 4 }, source[3].Take(0..^1).ToArray()); + Assert.Equal(1, source[3].Take(0..^4).ToArray().Single()); + Assert.Empty(source[3].Take(0..^5).ToArray()); + Assert.Empty(source[3].Take(0..^15).ToArray()); + + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[4].Take(^5..^0).ToArray()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[4].Take(^6..^0).ToArray()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[4].Take(^45..^0).ToArray()); + Assert.Equal(new[] { 1, 2, 3, 4 }, source[4].Take(^5..^1).ToArray()); + Assert.Equal(1, source[4].Take(^5..^4).ToArray().Single()); + Assert.Empty(source[4].Take(^5..^5).ToArray()); + Assert.Empty(source[4].Take(^15..^5).ToArray()); } [Fact] public void ToArrayNotList() { - 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()); - Assert.Equal(new[] { 1, 2, 3, 4 }, source.Take(4).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()); + var source = Repeat(_ => ForceNotCollection(new[] { 1, 2, 3, 4, 5 }), 5); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[0].Take(5).ToArray()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[0].Take(6).ToArray()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[0].Take(40).ToArray()); + Assert.Equal(new[] { 1, 2, 3, 4 }, source[0].Take(4).ToArray()); + Assert.Equal(1, source[0].Take(1).ToArray().Single()); + Assert.Empty(source[0].Take(0).ToArray()); + Assert.Empty(source[0].Take(-10).ToArray()); + + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[1].Take(0..5).ToArray()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[1].Take(0..6).ToArray()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[1].Take(0..40).ToArray()); + Assert.Equal(new[] { 1, 2, 3, 4 }, source[1].Take(0..4).ToArray()); + Assert.Equal(1, source[1].Take(0..1).ToArray().Single()); + Assert.Empty(source[1].Take(0..0).ToArray()); + + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[2].Take(^5..5).ToArray()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[2].Take(^5..6).ToArray()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[2].Take(^5..40).ToArray()); + Assert.Equal(new[] { 1, 2, 3, 4 }, source[2].Take(^5..4).ToArray()); + Assert.Equal(1, source[2].Take(^5..1).ToArray().Single()); + Assert.Empty(source[2].Take(^5..0).ToArray()); + Assert.Empty(source[2].Take(^15..0).ToArray()); + + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[3].Take(0..^0).ToArray()); + Assert.Equal(new[] { 1, 2, 3, 4 }, source[3].Take(0..^1).ToArray()); + Assert.Equal(1, source[3].Take(0..^4).ToArray().Single()); + Assert.Empty(source[3].Take(0..^5).ToArray()); + Assert.Empty(source[3].Take(0..^15).ToArray()); + + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[4].Take(^5..^0).ToArray()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[4].Take(^6..^0).ToArray()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[4].Take(^45..^0).ToArray()); + Assert.Equal(new[] { 1, 2, 3, 4 }, source[4].Take(^5..^1).ToArray()); + Assert.Equal(1, source[4].Take(^5..^4).ToArray().Single()); + Assert.Empty(source[4].Take(^5..^5).ToArray()); + Assert.Empty(source[4].Take(^15..^5).ToArray()); } [Fact] public void ToList() { - var source = 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()); - Assert.Equal(new[] { 1, 2, 3, 4 }, source.Take(4).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()); + var source = Repeat(_ => new[] { 1, 2, 3, 4, 5 }, 5); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[0].Take(5).ToList()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[0].Take(6).ToList()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[0].Take(40).ToList()); + Assert.Equal(new[] { 1, 2, 3, 4 }, source[0].Take(4).ToList()); + Assert.Equal(1, source[0].Take(1).ToList().Single()); + Assert.Empty(source[0].Take(0).ToList()); + Assert.Empty(source[0].Take(-10).ToList()); + + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[1].Take(0..5).ToList()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[1].Take(0..6).ToList()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[1].Take(0..40).ToList()); + Assert.Equal(new[] { 1, 2, 3, 4 }, source[1].Take(0..4).ToList()); + Assert.Equal(1, source[1].Take(0..1).ToList().Single()); + Assert.Empty(source[1].Take(0..0).ToList()); + + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[2].Take(^5..5).ToList()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[2].Take(^5..6).ToList()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[2].Take(^5..40).ToList()); + Assert.Equal(new[] { 1, 2, 3, 4 }, source[2].Take(^5..4).ToList()); + Assert.Equal(1, source[2].Take(^5..1).ToList().Single()); + Assert.Empty(source[2].Take(^5..0).ToList()); + Assert.Empty(source[2].Take(^15..0).ToList()); + + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[3].Take(0..^0).ToList()); + Assert.Equal(new[] { 1, 2, 3, 4 }, source[3].Take(0..^1).ToList()); + Assert.Equal(1, source[3].Take(0..^4).ToList().Single()); + Assert.Empty(source[3].Take(0..^5).ToList()); + Assert.Empty(source[3].Take(0..^15).ToList()); + + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[4].Take(^5..^0).ToList()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[4].Take(^6..^0).ToList()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[4].Take(^45..^0).ToList()); + Assert.Equal(new[] { 1, 2, 3, 4 }, source[4].Take(^5..^1).ToList()); + Assert.Equal(1, source[4].Take(^5..^4).ToList().Single()); + Assert.Empty(source[4].Take(^5..^5).ToList()); + Assert.Empty(source[4].Take(^15..^5).ToList()); } [Fact] public void ToListNotList() { - 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()); - Assert.Equal(new[] { 1, 2, 3, 4 }, source.Take(4).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()); + var source = Repeat(_ => ForceNotCollection(new[] { 1, 2, 3, 4, 5 }), 5); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[0].Take(5).ToList()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[0].Take(6).ToList()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[0].Take(40).ToList()); + Assert.Equal(new[] { 1, 2, 3, 4 }, source[0].Take(4).ToList()); + Assert.Equal(1, source[0].Take(1).ToList().Single()); + Assert.Empty(source[0].Take(0).ToList()); + Assert.Empty(source[0].Take(-10).ToList()); + + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[1].Take(0..5).ToList()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[1].Take(0..6).ToList()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[1].Take(0..40).ToList()); + Assert.Equal(new[] { 1, 2, 3, 4 }, source[1].Take(0..4).ToList()); + Assert.Equal(1, source[1].Take(0..1).ToList().Single()); + Assert.Empty(source[1].Take(0..0).ToList()); + + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[2].Take(^5..5).ToList()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[2].Take(^5..6).ToList()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[2].Take(^5..40).ToList()); + Assert.Equal(new[] { 1, 2, 3, 4 }, source[2].Take(^5..4).ToList()); + Assert.Equal(1, source[2].Take(^5..1).ToList().Single()); + Assert.Empty(source[2].Take(^5..0).ToList()); + Assert.Empty(source[2].Take(^15..0).ToList()); + + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[3].Take(0..^0).ToList()); + Assert.Equal(new[] { 1, 2, 3, 4 }, source[3].Take(0..^1).ToList()); + Assert.Equal(1, source[3].Take(0..^4).ToList().Single()); + Assert.Empty(source[3].Take(0..^5).ToList()); + Assert.Empty(source[3].Take(0..^15).ToList()); + + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[4].Take(^5..^0).ToList()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[4].Take(^6..^0).ToList()); + Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[4].Take(^45..^0).ToList()); + Assert.Equal(new[] { 1, 2, 3, 4 }, source[4].Take(^5..^1).ToList()); + Assert.Equal(1, source[4].Take(^5..^4).ToList().Single()); + Assert.Empty(source[4].Take(^5..^5).ToList()); + Assert.Empty(source[4].Take(^15..^5).ToList()); } [Fact] public void TakeCanOnlyBeOneList() { - var source = 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)); + var source = Repeat(_ => new[] { 2, 4, 6, 8, 10 }, 5); + Assert.Equal(new[] { 2 }, source[0].Take(1)); + Assert.Equal(new[] { 4 }, source[0].Skip(1).Take(1)); + Assert.Equal(new[] { 6 }, source[0].Take(3).Skip(2)); + Assert.Equal(new[] { 2 }, source[0].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[1].Take(0..1)); + Assert.Equal(new[] { 4 }, source[1].Skip(1).Take(0..1)); + Assert.Equal(new[] { 6 }, source[1].Take(0..3).Skip(2)); + Assert.Equal(new[] { 2 }, source[1].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[2].Take(^5..1)); + Assert.Equal(new[] { 4 }, source[2].Skip(1).Take(^4..1)); + Assert.Equal(new[] { 6 }, source[2].Take(^5..3).Skip(2)); + Assert.Equal(new[] { 2 }, source[2].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[3].Take(0..^4)); + Assert.Equal(new[] { 4 }, source[3].Skip(1).Take(0..^3)); + Assert.Equal(new[] { 6 }, source[3].Take(0..^2).Skip(2)); + Assert.Equal(new[] { 2 }, source[3].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)); + Assert.Equal(new[] { 2 }, source[4].Take(^5..^4)); + Assert.Equal(new[] { 4 }, source[4].Skip(1).Take(^4..^3)); + Assert.Equal(new[] { 6 }, source[4].Take(^5..^2).Skip(2)); + Assert.Equal(new[] { 2 }, source[4].Take(^5..^2).Take(^4..^2)); } [Fact] public void TakeCanOnlyBeOneNotList() { - 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)); + var source = Repeat(_ => ForceNotCollection(new[] { 2, 4, 6, 8, 10 }), 5); + Assert.Equal(new[] { 2 }, source[0].Take(1)); + Assert.Equal(new[] { 4 }, source[0].Skip(1).Take(1)); + Assert.Equal(new[] { 6 }, source[0].Take(3).Skip(2)); + Assert.Equal(new[] { 2 }, source[0].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[0].Take(0..1)); + Assert.Equal(new[] { 4 }, source[0].Skip(1).Take(0..1)); + Assert.Equal(new[] { 6 }, source[0].Take(0..3).Skip(2)); + Assert.Equal(new[] { 2 }, source[0].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[2].Take(^5..1)); + Assert.Equal(new[] { 4 }, source[2].Skip(1).Take(^4..1)); + Assert.Equal(new[] { 6 }, source[2].Take(^5..3).Skip(2)); + Assert.Equal(new[] { 2 }, source[2].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[3].Take(0..^4)); + Assert.Equal(new[] { 4 }, source[3].Skip(1).Take(0..^3)); + Assert.Equal(new[] { 6 }, source[3].Take(0..^2).Skip(2)); + Assert.Equal(new[] { 2 }, source[3].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)); + Assert.Equal(new[] { 2 }, source[4].Take(^5..^4)); + Assert.Equal(new[] { 4 }, source[4].Skip(1).Take(^4..^3)); + Assert.Equal(new[] { 6 }, source[4].Take(^5..^2).Skip(2)); + Assert.Equal(new[] { 2 }, source[4].Take(^5..^2).Take(^4..^2)); } [Fact] public void RepeatEnumerating() { - var source = new[] { 1, 2, 3, 4, 5 }; + var source = Repeat(_ => new[] { 1, 2, 3, 4, 5 }, 5); var taken1 = source.Take(3); Assert.Equal(taken1, taken1); @@ -1026,7 +1038,7 @@ public void RepeatEnumerating() [Fact] public void RepeatEnumeratingNotList() { - var source = ForceNotCollection(new[] { 1, 2, 3, 4, 5 }); + var source = Repeat(_ => ForceNotCollection(new[] { 1, 2, 3, 4, 5 }), 5); var taken1 = source.Take(3); Assert.Equal(taken1, taken1); @@ -1306,39 +1318,38 @@ public void DisposeSource(int sourceCount, int count) [Fact] public void OutOfBoundNoException() { - var 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)); - + 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] @@ -1378,6 +1389,80 @@ public void OutOfBoundNoExceptionNotList() Assert.Empty(ForceNotCollection(source).Take(^int.MaxValue..^int.MaxValue)); } + [Fact] + public void OutOfBoundNoExceptionListPartition() + { + var source = new[] { 1, 2, 3, 4, 5 }; + + Assert.Equal(source, ListPartition(source).Take(0..6)); + Assert.Equal(source, ListPartition(source).Take(0..int.MaxValue)); + + Assert.Equal(new int[] { 1, 2, 3, 4 }, ListPartition(source).Take(^10..4)); + Assert.Equal(new int[] { 1, 2, 3, 4 }, ListPartition(source).Take(^int.MaxValue..4)); + Assert.Equal(source, ListPartition(source).Take(^10..6)); + Assert.Equal(source, ListPartition(source).Take(^int.MaxValue..6)); + Assert.Equal(source, ListPartition(source).Take(^10..int.MaxValue)); + Assert.Equal(source, ListPartition(source).Take(^int.MaxValue..int.MaxValue)); + + Assert.Empty(ListPartition(source).Take(0..^6)); + Assert.Empty(ListPartition(source).Take(0..^int.MaxValue)); + Assert.Empty(ListPartition(source).Take(4..^6)); + Assert.Empty(ListPartition(source).Take(4..^int.MaxValue)); + Assert.Empty(ListPartition(source).Take(6..^6)); + Assert.Empty(ListPartition(source).Take(6..^int.MaxValue)); + Assert.Empty(ListPartition(source).Take(int.MaxValue..^6)); + Assert.Empty(ListPartition(source).Take(int.MaxValue..^int.MaxValue)); + + Assert.Equal(new int[] { 1, 2, 3, 4 }, ListPartition(source).Take(^10..^1)); + Assert.Equal(new int[] { 1, 2, 3, 4 }, ListPartition(source).Take(^int.MaxValue..^1)); + Assert.Empty(ListPartition(source).Take(^0..^6)); + Assert.Empty(ListPartition(source).Take(^1..^6)); + Assert.Empty(ListPartition(source).Take(^6..^6)); + Assert.Empty(ListPartition(source).Take(^10..^6)); + Assert.Empty(ListPartition(source).Take(^int.MaxValue..^6)); + Assert.Empty(ListPartition(source).Take(^0..^int.MaxValue)); + Assert.Empty(ListPartition(source).Take(^1..^int.MaxValue)); + Assert.Empty(ListPartition(source).Take(^6..^int.MaxValue)); + Assert.Empty(ListPartition(source).Take(^int.MaxValue..^int.MaxValue)); + } + + [Fact] + public void OutOfBoundNoExceptionEnumerablePartition() + { + var source = new[] { 1, 2, 3, 4, 5 }; + + Assert.Equal(source, EnumerablePartition(source).Take(0..6)); + Assert.Equal(source, EnumerablePartition(source).Take(0..int.MaxValue)); + + Assert.Equal(new int[] { 1, 2, 3, 4 }, EnumerablePartition(source).Take(^10..4)); + Assert.Equal(new int[] { 1, 2, 3, 4 }, EnumerablePartition(source).Take(^int.MaxValue..4)); + Assert.Equal(source, EnumerablePartition(source).Take(^10..6)); + Assert.Equal(source, EnumerablePartition(source).Take(^int.MaxValue..6)); + Assert.Equal(source, EnumerablePartition(source).Take(^10..int.MaxValue)); + Assert.Equal(source, EnumerablePartition(source).Take(^int.MaxValue..int.MaxValue)); + + Assert.Empty(EnumerablePartition(source).Take(0..^6)); + Assert.Empty(EnumerablePartition(source).Take(0..^int.MaxValue)); + Assert.Empty(EnumerablePartition(source).Take(4..^6)); + Assert.Empty(EnumerablePartition(source).Take(4..^int.MaxValue)); + Assert.Empty(EnumerablePartition(source).Take(6..^6)); + Assert.Empty(EnumerablePartition(source).Take(6..^int.MaxValue)); + Assert.Empty(EnumerablePartition(source).Take(int.MaxValue..^6)); + Assert.Empty(EnumerablePartition(source).Take(int.MaxValue..^int.MaxValue)); + + Assert.Equal(new int[] { 1, 2, 3, 4 }, EnumerablePartition(source).Take(^10..^1)); + Assert.Equal(new int[] { 1, 2, 3, 4 }, EnumerablePartition(source).Take(^int.MaxValue..^1)); + Assert.Empty(EnumerablePartition(source).Take(^0..^6)); + Assert.Empty(EnumerablePartition(source).Take(^1..^6)); + Assert.Empty(EnumerablePartition(source).Take(^6..^6)); + Assert.Empty(EnumerablePartition(source).Take(^10..^6)); + Assert.Empty(EnumerablePartition(source).Take(^int.MaxValue..^6)); + Assert.Empty(EnumerablePartition(source).Take(^0..^int.MaxValue)); + Assert.Empty(EnumerablePartition(source).Take(^1..^int.MaxValue)); + Assert.Empty(EnumerablePartition(source).Take(^6..^int.MaxValue)); + Assert.Empty(EnumerablePartition(source).Take(^int.MaxValue..^int.MaxValue)); + } + [Fact] public void MutableSource() { @@ -1437,47 +1522,47 @@ public void MutableSourceNotList() [Fact] public void NonEmptySource_ConsistencyWithCountable() { - int[] source = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + 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)); + 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)); + 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(..)); + 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)); + 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)); + 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)); + 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)); + 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] @@ -1621,12 +1706,12 @@ public void NonEmptySource_ConsistencyWithCountable_EnumerablePartition() [Fact] public void NonEmptySource_DoNotThrowException() { - int[] source = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + 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)); + 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] @@ -1665,53 +1750,53 @@ public void NonEmptySource_DoNotThrowException_EnumerablePartition() [Fact] public void EmptySource_DoNotThrowException() { - int[] source = { }; + 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)); + 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)); + 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(..)); + 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)); + 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)); + 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)); + 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)); + 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)); + 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] From e9922bf036130fd5da638c61e7bd4ba01e598297 Mon Sep 17 00:00:00 2001 From: Dixin Date: Sat, 6 Feb 2021 13:46:53 -0800 Subject: [PATCH 18/35] Implement dotnet/runtime#28776: LINQ APIs for index and range. Code review update. --- .../System.Linq/src/System/Linq/ElementAt.cs | 96 +++++++------------ .../System.Linq/src/System/Linq/Take.cs | 41 ++++---- src/libraries/System.Linq/tests/TakeTests.cs | 19 ++-- 3 files changed, 68 insertions(+), 88 deletions(-) diff --git a/src/libraries/System.Linq/src/System/Linq/ElementAt.cs b/src/libraries/System.Linq/src/System/Linq/ElementAt.cs index 7de94845e8eca2..6aabd4a4eb4f35 100644 --- a/src/libraries/System.Linq/src/System/Linq/ElementAt.cs +++ b/src/libraries/System.Linq/src/System/Linq/ElementAt.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; namespace System.Linq { @@ -73,59 +74,9 @@ public static TSource ElementAt(this IEnumerable source, Index return source.ElementAt(index.Value); } - int indexFromEnd = index.Value; - Debug.Assert(indexFromEnd >= 0); - if (indexFromEnd == 0) - { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); - } - - if (source is IPartition partition) - { - int count = partition.GetCount(onlyIfCheap: true); - if (count == 0) - { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); - } - - if (count > 0) - { - if (indexFromEnd <= count) - { - TSource? element = partition.TryGetElementAt(count - indexFromEnd, out bool found); - if (found) - { - return element!; - } - } - - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); - } - } - else if (source is IList list) + if (TryGetElementAt(source, index.Value, out TSource? result)) { - return list[index]; - } - - using IEnumerator e = source.GetEnumerator(); - if (e.MoveNext()) - { - Queue queue = new(); - queue.Enqueue(e.Current); - while (e.MoveNext()) - { - if (queue.Count == indexFromEnd) - { - queue.Dequeue(); - } - - queue.Enqueue(e.Current); - } - - if (queue.Count == indexFromEnd) - { - return queue.Dequeue(); - } + return result; } ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); @@ -195,11 +146,18 @@ public static TSource ElementAt(this IEnumerable source, Index return source.ElementAtOrDefault(index.Value); } - int indexFromEnd = index.Value; + TryGetElementAt(source, index.Value, out TSource? result); + return result; + } + + private static bool TryGetElementAt(IEnumerable source, int indexFromEnd, [NotNullWhen(true)] out TSource? result) + { Debug.Assert(indexFromEnd >= 0); + + result = default; if (indexFromEnd == 0) { - return default; + return false; } if (source is IPartition partition) @@ -207,26 +165,36 @@ public static TSource ElementAt(this IEnumerable source, Index int count = partition.GetCount(onlyIfCheap: true); if (count == 0) { - return default; + return false; } if (count > 0) { - return indexFromEnd <= count - ? partition.TryGetElementAt(count - indexFromEnd, out bool _) - : default; + if (indexFromEnd <= count) + { + result = partition.TryGetElementAt(count - indexFromEnd, out bool found); + return found; + } + + return false; } } else if (source is IList list) { int count = list.Count; - return indexFromEnd <= count ? list[count - indexFromEnd] : default; + if (indexFromEnd <= count) + { + result = list[count - indexFromEnd]!; + return true; + } + + return false; } using IEnumerator e = source.GetEnumerator(); if (!e.MoveNext()) { - return default; + return false; } Queue queue = new(); @@ -241,7 +209,13 @@ public static TSource ElementAt(this IEnumerable source, Index queue.Enqueue(e.Current); } - return queue.Count == indexFromEnd ? queue.Dequeue() : default; + if (queue.Count == indexFromEnd) + { + result = queue.Dequeue()!; + return true; + } + + 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 260bb10bc82314..e1db7bc013ab76 100644 --- a/src/libraries/System.Linq/src/System/Linq/Take.cs +++ b/src/libraries/System.Linq/src/System/Linq/Take.cs @@ -44,16 +44,18 @@ public static IEnumerable Take(this IEnumerable sourc Debug.Assert(startIndex >= 0); Debug.Assert(endIndex >= 0); - if (!isStartIndexFromEnd && !isEndIndexFromEnd) + if (isStartIndexFromEnd) + { + if (startIndex == 0 || isEndIndexFromEnd && endIndex >= startIndex) + { + return Empty(); + } + } + else if (!isEndIndexFromEnd) { return startIndex >= endIndex ? Empty() - : source switch - { - IPartition partition => partition.Skip(startIndex).Take(endIndex - startIndex), - IList list => new ListPartition(list, startIndex, endIndex - 1), - _ => new EnumerablePartition(source, startIndex, endIndex - 1) - }; + : source.Skip(startIndex).Take(endIndex - startIndex); } return TakeIterator(source, isStartIndexFromEnd, startIndex, isEndIndexFromEnd, endIndex); @@ -63,17 +65,14 @@ private static IEnumerable TakeIterator( IEnumerable source, bool isStartIndexFromEnd, int startIndex, bool isEndIndexFromEnd, int endIndex) { Debug.Assert(source != null); - Debug.Assert(startIndex >= 0); + 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 (startIndex == 0) - { - yield break; - } - - using IEnumerator e = source.GetEnumerator(); if (!e.MoveNext()) { yield break; @@ -124,15 +123,19 @@ private static IEnumerable TakeIterator( } else { - using IEnumerator e = source.GetEnumerator(); if (!e.MoveNext()) { yield break; } int index = 0; - while (index < startIndex && e.MoveNext()) + while (index < startIndex) { + if (!e.MoveNext()) + { + yield break; + } + checked { index++; @@ -169,11 +172,7 @@ private static IEnumerable TakeIterator( } else { - if (startIndex >= endIndex) - { - yield break; - } - + Debug.Assert(index < endIndex); yield return e.Current; while (checked(++index) < endIndex && e.MoveNext()) { diff --git a/src/libraries/System.Linq/tests/TakeTests.cs b/src/libraries/System.Linq/tests/TakeTests.cs index a444b77e565158..85147b85750717 100644 --- a/src/libraries/System.Linq/tests/TakeTests.cs +++ b/src/libraries/System.Linq/tests/TakeTests.cs @@ -1294,24 +1294,31 @@ public void DisposeSource(int sourceCount, int 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()); - int expected1 = end == 0 ? 0 : -1; // When startIndex is not from end and endIndex is not from end and startIndex >= endIndex, Take(Range) returns an empty array. + // When startIndex end and endIndex are both not from end and startIndex >= endIndex, Take(Range) returns an empty array. + int expected1 = end == 0 ? 0 : -1; Assert.Equal(expected1, state[1]); - IEnumerator iterator2 = source[2].Take(^Math.Max(sourceCount, end)..end).GetEnumerator(); + 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()); - int expected2 = Math.Max(sourceCount, end) == 0 ? 0 : -1; // When startIndex is ^0, Take(Range) returns an empty iterator. + // When startIndex is ^0, Take(Range) returns an empty array. + int expected2 = startIndexFromEnd == 0 ? 0 : -1; Assert.Equal(expected2, state[2]); - IEnumerator iterator3 = source[3].Take(0..^Math.Max(0, sourceCount - end)).GetEnumerator(); + 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.Equal(-1, state[3]); - IEnumerator iterator4 = source[4].Take(^Math.Max(sourceCount, end)..^Math.Max(0, sourceCount - end)).GetEnumerator(); + 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()); - int expected4 = Math.Max(sourceCount, end) == 0 ? 0 : -1; // When startIndex is ^0, Take(Range) returns an empty iterator. + // When startIndex is ^0, + // or when startIndex and endIndex are both from end and startIndex <= endIndexFromEnd, Take(Range) returns an empty array. + int expected4 = startIndexFromEnd == 0 || startIndexFromEnd <= endIndexFromEnd ? 0 : -1; Assert.Equal(expected4, state[4]); } From 52b8617ceb46e8bc949837f2dbab4e49edfd4bbb Mon Sep 17 00:00:00 2001 From: Dixin Date: Sun, 7 Feb 2021 12:14:00 -0800 Subject: [PATCH 19/35] Implement dotnet/runtime#28776: LINQ APIs for index and range. Code review update. --- .../System.Linq/src/System/Linq/ElementAt.cs | 13 ++++++------- src/libraries/System.Linq/src/System/Linq/Take.cs | 14 ++------------ 2 files changed, 8 insertions(+), 19 deletions(-) diff --git a/src/libraries/System.Linq/src/System/Linq/ElementAt.cs b/src/libraries/System.Linq/src/System/Linq/ElementAt.cs index 6aabd4a4eb4f35..22bc74a73b3fae 100644 --- a/src/libraries/System.Linq/src/System/Linq/ElementAt.cs +++ b/src/libraries/System.Linq/src/System/Linq/ElementAt.cs @@ -74,13 +74,12 @@ public static TSource ElementAt(this IEnumerable source, Index return source.ElementAt(index.Value); } - if (TryGetElementAt(source, index.Value, out TSource? result)) + if (!TryGetElementAt(source, index.Value, out TSource? result)) { - return result; + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); } - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); - return default; + return result!; } public static TSource? ElementAtOrDefault(this IEnumerable source, int index) @@ -150,7 +149,7 @@ public static TSource ElementAt(this IEnumerable source, Index return result; } - private static bool TryGetElementAt(IEnumerable source, int indexFromEnd, [NotNullWhen(true)] out TSource? result) + private static bool TryGetElementAt(IEnumerable source, int indexFromEnd, [MaybeNullWhen(false)] out TSource? result) { Debug.Assert(indexFromEnd >= 0); @@ -184,7 +183,7 @@ private static bool TryGetElementAt(IEnumerable source, int in int count = list.Count; if (indexFromEnd <= count) { - result = list[count - indexFromEnd]!; + result = list[count - indexFromEnd]; return true; } @@ -211,7 +210,7 @@ private static bool TryGetElementAt(IEnumerable source, int in if (queue.Count == indexFromEnd) { - result = queue.Dequeue()!; + result = queue.Dequeue(); return true; } diff --git a/src/libraries/System.Linq/src/System/Linq/Take.cs b/src/libraries/System.Linq/src/System/Linq/Take.cs index e1db7bc013ab76..c6db5760a08a22 100644 --- a/src/libraries/System.Linq/src/System/Linq/Take.cs +++ b/src/libraries/System.Linq/src/System/Linq/Take.cs @@ -46,7 +46,7 @@ public static IEnumerable Take(this IEnumerable sourc if (isStartIndexFromEnd) { - if (startIndex == 0 || isEndIndexFromEnd && endIndex >= startIndex) + if (startIndex == 0 || (isEndIndexFromEnd && endIndex >= startIndex)) { return Empty(); } @@ -123,13 +123,8 @@ private static IEnumerable TakeIterator( } else { - if (!e.MoveNext()) - { - yield break; - } - int index = 0; - while (index < startIndex) + while (index <= startIndex) { if (!e.MoveNext()) { @@ -142,11 +137,6 @@ private static IEnumerable TakeIterator( } } - if (index != startIndex) - { - yield break; - } - if (isEndIndexFromEnd) { if (endIndex > 0) From 60dff4702f3916fbfb85e7e0b5fc347154e43abe Mon Sep 17 00:00:00 2001 From: Dixin Date: Mon, 8 Feb 2021 21:14:12 -0800 Subject: [PATCH 20/35] Implement dotnet/runtime#28776: LINQ APIs for index and range. --- .../System.Linq/src/System/Linq/ElementAt.cs | 110 +++++++++--------- .../System.Linq/tests/ElementAtTests.cs | 104 +++++++++++++++++ 2 files changed, 162 insertions(+), 52 deletions(-) diff --git a/src/libraries/System.Linq/src/System/Linq/ElementAt.cs b/src/libraries/System.Linq/src/System/Linq/ElementAt.cs index 22bc74a73b3fae..1faa5d6fb72ff8 100644 --- a/src/libraries/System.Linq/src/System/Linq/ElementAt.cs +++ b/src/libraries/System.Linq/src/System/Linq/ElementAt.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; @@ -24,28 +25,13 @@ 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); @@ -74,12 +60,12 @@ public static TSource ElementAt(this IEnumerable source, Index return source.ElementAt(index.Value); } - if (!TryGetElementAt(source, index.Value, out TSource? result)) + if (!TryGetElementFromEnd(source, index.Value, out TSource? element)) { ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); } - return result!; + return element!; } public static TSource? ElementAtOrDefault(this IEnumerable source, int index) @@ -94,31 +80,17 @@ public static TSource ElementAt(this IEnumerable source, Index return partition.TryGetElementAt(index, out bool _); } - if (index >= 0) + if (source is IList list) { - if (source is IList list) - { - if (index < list.Count) - { - return list[index]; - } - } - else + if (index >= 0 && index < list.Count) { - 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; + } return default; } @@ -145,15 +117,39 @@ public static TSource ElementAt(this IEnumerable source, Index return source.ElementAtOrDefault(index.Value); } - TryGetElementAt(source, index.Value, out TSource? result); - return result; + TryGetElementFromEnd(source, index.Value, out TSource? element); + return element; } - private static bool TryGetElementAt(IEnumerable source, int indexFromEnd, [MaybeNullWhen(false)] out TSource? result) + private static bool TryGetElement(IEnumerable source, int index, [MaybeNullWhen(false)] out TSource element) { + Debug.Assert(source != null); + + if (index >= 0) + { + using IEnumerator e = source.GetEnumerator(); + while (e.MoveNext()) + { + if (index == 0) + { + element = e.Current; + return true; + } + + index--; + } + } + + element = default; + return false; + } + + private static bool TryGetElementFromEnd(IEnumerable source, int indexFromEnd, [MaybeNullWhen(false)] out TSource element) + { + Debug.Assert(source != null); Debug.Assert(indexFromEnd >= 0); - result = default; + element = default; if (indexFromEnd == 0) { return false; @@ -171,7 +167,7 @@ private static bool TryGetElementAt(IEnumerable source, int in { if (indexFromEnd <= count) { - result = partition.TryGetElementAt(count - indexFromEnd, out bool found); + element = partition.TryGetElementAt(count - indexFromEnd, out bool found); return found; } @@ -181,14 +177,24 @@ private static bool TryGetElementAt(IEnumerable source, int in else if (source is IList list) { int count = list.Count; - if (indexFromEnd <= count) + if (count > 0 && indexFromEnd <= count) { - result = list[count - indexFromEnd]; + element = list[count - indexFromEnd]; return true; } return false; } + else if (source is ICollection genericCollection) + { + int count = genericCollection.Count; + return count > 0 && TryGetElement(source, count - indexFromEnd, out element); + } + else if (source is ICollection collection) + { + int count = collection.Count; + return count > 0 && TryGetElement(source, count - indexFromEnd, out element); + } using IEnumerator e = source.GetEnumerator(); if (!e.MoveNext()) @@ -210,7 +216,7 @@ private static bool TryGetElementAt(IEnumerable source, int in if (queue.Count == indexFromEnd) { - result = queue.Dequeue(); + element = queue.Dequeue(); return true; } diff --git a/src/libraries/System.Linq/tests/ElementAtTests.cs b/src/libraries/System.Linq/tests/ElementAtTests.cs index 979925ed3e8df7..08118afcd5d716 100644 --- a/src/libraries/System.Linq/tests/ElementAtTests.cs +++ b/src/libraries/System.Linq/tests/ElementAtTests.cs @@ -274,6 +274,68 @@ public void NonEmptySource_Consistency_EnumerablePartition() AssertExtensions.Throws("index", () => EnumerablePartition(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)); + + AssertExtensions.Throws("index", () => new TestCollection(source).ElementAt(-1)); + AssertExtensions.Throws("index", () => new TestCollection(source).ElementAt(^11)); + + AssertExtensions.Throws("index", () => new TestCollection(source).ElementAt(10)); + AssertExtensions.Throws("index", () => new TestCollection(source).ElementAt(new Index(10))); + AssertExtensions.Throws("index", () => new TestCollection(source).ElementAt(^0)); + + AssertExtensions.Throws("index", () => new TestCollection(source).ElementAt(int.MinValue)); + AssertExtensions.Throws("index", () => new TestCollection(source).ElementAt(^int.MaxValue)); + + AssertExtensions.Throws("index", () => new TestCollection(source).ElementAt(int.MaxValue)); + AssertExtensions.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)); + + AssertExtensions.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(-1)); + AssertExtensions.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(^11)); + + AssertExtensions.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(10)); + AssertExtensions.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(new Index(10))); + AssertExtensions.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(^0)); + + AssertExtensions.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(int.MinValue)); + AssertExtensions.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(^int.MaxValue)); + + AssertExtensions.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(int.MaxValue)); + AssertExtensions.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(new Index(int.MaxValue))); + } + [Fact] public void EmptySource_Consistency() { @@ -357,5 +419,47 @@ public void EmptySource_Consistency_EnumerablePartition() AssertExtensions.Throws("index", () => EnumerablePartition(source).ElementAt(int.MaxValue)); AssertExtensions.Throws("index", () => EnumerablePartition(source).ElementAt(new Index(int.MaxValue))); } + + [Fact] + public void EmptySource_Consistency_Collection() + { + int[] source = { }; + + AssertExtensions.Throws("index", () => new TestCollection(source).ElementAt(1)); + AssertExtensions.Throws("index", () => new TestCollection(source).ElementAt(-1)); + AssertExtensions.Throws("index", () => new TestCollection(source).ElementAt(new Index(1))); + AssertExtensions.Throws("index", () => new TestCollection(source).ElementAt(^1)); + + AssertExtensions.Throws("index", () => new TestCollection(source).ElementAt(0)); + AssertExtensions.Throws("index", () => new TestCollection(source).ElementAt(new Index(0))); + AssertExtensions.Throws("index", () => new TestCollection(source).ElementAt(^0)); + + AssertExtensions.Throws("index", () => new TestCollection(source).ElementAt(int.MinValue)); + AssertExtensions.Throws("index", () => new TestCollection(source).ElementAt(^int.MaxValue)); + + AssertExtensions.Throws("index", () => new TestCollection(source).ElementAt(int.MaxValue)); + AssertExtensions.Throws("index", () => new TestCollection(source).ElementAt(new Index(int.MaxValue))); + } + + [Fact] + public void EmptySource_Consistency_NonGenericCollection() + { + int[] source = { }; + + AssertExtensions.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(1)); + AssertExtensions.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(-1)); + AssertExtensions.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(new Index(1))); + AssertExtensions.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(^1)); + + AssertExtensions.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(0)); + AssertExtensions.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(new Index(0))); + AssertExtensions.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(^0)); + + AssertExtensions.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(int.MinValue)); + AssertExtensions.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(^int.MaxValue)); + + AssertExtensions.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(int.MaxValue)); + AssertExtensions.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(new Index(int.MaxValue))); + } } } From 3d839c574650cf6f8846c65ceb8c90db12d06e52 Mon Sep 17 00:00:00 2001 From: Dixin Date: Fri, 12 Feb 2021 14:38:50 -0800 Subject: [PATCH 21/35] Implement dotnet/runtime#28776: LINQ APIs for index and range. Code review update. --- src/libraries/System.Linq/src/System/Linq/ElementAt.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Linq/src/System/Linq/ElementAt.cs b/src/libraries/System.Linq/src/System/Linq/ElementAt.cs index 1faa5d6fb72ff8..1f2d6eb70f550b 100644 --- a/src/libraries/System.Linq/src/System/Linq/ElementAt.cs +++ b/src/libraries/System.Linq/src/System/Linq/ElementAt.cs @@ -31,7 +31,7 @@ public static TSource ElementAt(this IEnumerable source, int i } else if (TryGetElement(source, index, out TSource? element)) { - return element!; + return element; } ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); @@ -65,7 +65,7 @@ public static TSource ElementAt(this IEnumerable source, Index ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); } - return element!; + return element; } public static TSource? ElementAtOrDefault(this IEnumerable source, int index) @@ -190,6 +190,11 @@ private static bool TryGetElementFromEnd(IEnumerable source, i int count = genericCollection.Count; return count > 0 && TryGetElement(source, count - indexFromEnd, out element); } + else if (source is IIListProvider listProvider) + { + int count = listProvider.GetCount(onlyIfCheap: false); + return count > 0 && TryGetElement(source, count - indexFromEnd, out element); + } else if (source is ICollection collection) { int count = collection.Count; From cb7553d842485abcd1dd9a09fc8ec1e9ab180960 Mon Sep 17 00:00:00 2001 From: Dixin Date: Sat, 13 Feb 2021 20:30:51 -0800 Subject: [PATCH 22/35] Implement dotnet/runtime#28776: LINQ APIs for index and range. --- .../System.Linq/src/System/Linq/ElementAt.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Linq/src/System/Linq/ElementAt.cs b/src/libraries/System.Linq/src/System/Linq/ElementAt.cs index 1f2d6eb70f550b..844824b65682ae 100644 --- a/src/libraries/System.Linq/src/System/Linq/ElementAt.cs +++ b/src/libraries/System.Linq/src/System/Linq/ElementAt.cs @@ -192,8 +192,16 @@ private static bool TryGetElementFromEnd(IEnumerable source, i } else if (source is IIListProvider listProvider) { - int count = listProvider.GetCount(onlyIfCheap: false); - return count > 0 && TryGetElement(source, count - indexFromEnd, out element); + int count = listProvider.GetCount(onlyIfCheap: true); + if (count == 0) + { + return false; + } + + if (count > 0) + { + return TryGetElement(source, count - indexFromEnd, out element); + } } else if (source is ICollection collection) { From e17dbd992691c433d4ea8d757b5c7c4b84f9d86f Mon Sep 17 00:00:00 2001 From: Dixin Date: Sat, 13 Feb 2021 23:28:40 -0800 Subject: [PATCH 23/35] Implement dotnet/runtime#28776: LINQ APIs for index and range. --- .../tests/ElementAtOrDefaultTests.cs | 116 +++--- .../System.Linq/tests/ElementAtTests.cs | 116 +++--- .../System.Linq/tests/EnumerableTests.cs | 16 +- src/libraries/System.Linq/tests/TakeTests.cs | 360 +++++++++--------- 4 files changed, 306 insertions(+), 302 deletions(-) diff --git a/src/libraries/System.Linq/tests/ElementAtOrDefaultTests.cs b/src/libraries/System.Linq/tests/ElementAtOrDefaultTests.cs index a511b28cc4237e..d17c00bc5b80d2 100644 --- a/src/libraries/System.Linq/tests/ElementAtOrDefaultTests.cs +++ b/src/libraries/System.Linq/tests/ElementAtOrDefaultTests.cs @@ -211,30 +211,30 @@ public void NonEmptySource_Consistency_ListPartition() { int?[] source = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; - Assert.Equal(5, ListPartition(source).ElementAtOrDefault(5)); - Assert.Equal(5, ListPartition(source).ElementAtOrDefault(new Index(5))); - Assert.Equal(5, ListPartition(source).ElementAtOrDefault(^5)); + 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, ListPartition(source).ElementAtOrDefault(0)); - Assert.Equal(0, ListPartition(source).ElementAtOrDefault(new Index(0))); - Assert.Equal(0, ListPartition(source).ElementAtOrDefault(^10)); + 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, ListPartition(source).ElementAtOrDefault(9)); - Assert.Equal(9, ListPartition(source).ElementAtOrDefault(new Index(9))); - Assert.Equal(9, ListPartition(source).ElementAtOrDefault(^1)); + 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(ListPartition(source).ElementAtOrDefault(-1)); - Assert.Null(ListPartition(source).ElementAtOrDefault(^11)); + Assert.Null(ListPartitionOrEmpty(source).ElementAtOrDefault(-1)); + Assert.Null(ListPartitionOrEmpty(source).ElementAtOrDefault(^11)); - Assert.Null(ListPartition(source).ElementAtOrDefault(10)); - Assert.Null(ListPartition(source).ElementAtOrDefault(new Index(10))); - Assert.Null(ListPartition(source).ElementAtOrDefault(^0)); + Assert.Null(ListPartitionOrEmpty(source).ElementAtOrDefault(10)); + Assert.Null(ListPartitionOrEmpty(source).ElementAtOrDefault(new Index(10))); + Assert.Null(ListPartitionOrEmpty(source).ElementAtOrDefault(^0)); - Assert.Null(ListPartition(source).ElementAtOrDefault(int.MinValue)); - Assert.Null(ListPartition(source).ElementAtOrDefault(^int.MaxValue)); + Assert.Null(ListPartitionOrEmpty(source).ElementAtOrDefault(int.MinValue)); + Assert.Null(ListPartitionOrEmpty(source).ElementAtOrDefault(^int.MaxValue)); - Assert.Null(ListPartition(source).ElementAtOrDefault(int.MaxValue)); - Assert.Null(ListPartition(source).ElementAtOrDefault(new Index(int.MaxValue))); + Assert.Null(ListPartitionOrEmpty(source).ElementAtOrDefault(int.MaxValue)); + Assert.Null(ListPartitionOrEmpty(source).ElementAtOrDefault(new Index(int.MaxValue))); } [Fact] @@ -242,30 +242,30 @@ public void NonEmptySource_Consistency_EnumerablePartition() { int?[] source = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; - Assert.Equal(5, EnumerablePartition(source).ElementAtOrDefault(5)); - Assert.Equal(5, EnumerablePartition(source).ElementAtOrDefault(new Index(5))); - Assert.Equal(5, EnumerablePartition(source).ElementAtOrDefault(^5)); + 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, EnumerablePartition(source).ElementAtOrDefault(0)); - Assert.Equal(0, EnumerablePartition(source).ElementAtOrDefault(new Index(0))); - Assert.Equal(0, EnumerablePartition(source).ElementAtOrDefault(^10)); + 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, EnumerablePartition(source).ElementAtOrDefault(9)); - Assert.Equal(9, EnumerablePartition(source).ElementAtOrDefault(new Index(9))); - Assert.Equal(9, EnumerablePartition(source).ElementAtOrDefault(^1)); + 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(EnumerablePartition(source).ElementAtOrDefault(-1)); - Assert.Null(EnumerablePartition(source).ElementAtOrDefault(^11)); + Assert.Null(EnumerablePartitionOrEmpty(source).ElementAtOrDefault(-1)); + Assert.Null(EnumerablePartitionOrEmpty(source).ElementAtOrDefault(^11)); - Assert.Null(EnumerablePartition(source).ElementAtOrDefault(10)); - Assert.Null(EnumerablePartition(source).ElementAtOrDefault(new Index(10))); - Assert.Null(EnumerablePartition(source).ElementAtOrDefault(^0)); + Assert.Null(EnumerablePartitionOrEmpty(source).ElementAtOrDefault(10)); + Assert.Null(EnumerablePartitionOrEmpty(source).ElementAtOrDefault(new Index(10))); + Assert.Null(EnumerablePartitionOrEmpty(source).ElementAtOrDefault(^0)); - Assert.Null(EnumerablePartition(source).ElementAtOrDefault(int.MinValue)); - Assert.Null(EnumerablePartition(source).ElementAtOrDefault(^int.MaxValue)); + Assert.Null(EnumerablePartitionOrEmpty(source).ElementAtOrDefault(int.MinValue)); + Assert.Null(EnumerablePartitionOrEmpty(source).ElementAtOrDefault(^int.MaxValue)); - Assert.Null(EnumerablePartition(source).ElementAtOrDefault(int.MaxValue)); - Assert.Null(EnumerablePartition(source).ElementAtOrDefault(new Index(int.MaxValue))); + Assert.Null(EnumerablePartitionOrEmpty(source).ElementAtOrDefault(int.MaxValue)); + Assert.Null(EnumerablePartitionOrEmpty(source).ElementAtOrDefault(new Index(int.MaxValue))); } [Fact] @@ -315,20 +315,20 @@ public void EmptySource_Consistency_ListPartition() { int?[] source = { }; - Assert.Null(ListPartition(source).ElementAtOrDefault(1)); - Assert.Null(ListPartition(source).ElementAtOrDefault(-1)); - Assert.Null(ListPartition(source).ElementAtOrDefault(new Index(1))); - Assert.Null(ListPartition(source).ElementAtOrDefault(^1)); + 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(ListPartition(source).ElementAtOrDefault(0)); - Assert.Null(ListPartition(source).ElementAtOrDefault(new Index(0))); - Assert.Null(ListPartition(source).ElementAtOrDefault(^0)); + Assert.Null(ListPartitionOrEmpty(source).ElementAtOrDefault(0)); + Assert.Null(ListPartitionOrEmpty(source).ElementAtOrDefault(new Index(0))); + Assert.Null(ListPartitionOrEmpty(source).ElementAtOrDefault(^0)); - Assert.Null(ListPartition(source).ElementAtOrDefault(int.MinValue)); - Assert.Null(ListPartition(source).ElementAtOrDefault(^int.MaxValue)); + Assert.Null(ListPartitionOrEmpty(source).ElementAtOrDefault(int.MinValue)); + Assert.Null(ListPartitionOrEmpty(source).ElementAtOrDefault(^int.MaxValue)); - Assert.Null(ListPartition(source).ElementAtOrDefault(int.MaxValue)); - Assert.Null(ListPartition(source).ElementAtOrDefault(new Index(int.MaxValue))); + Assert.Null(ListPartitionOrEmpty(source).ElementAtOrDefault(int.MaxValue)); + Assert.Null(ListPartitionOrEmpty(source).ElementAtOrDefault(new Index(int.MaxValue))); } [Fact] @@ -336,20 +336,20 @@ public void EmptySource_Consistency_EnumerablePartition() { int?[] source = { }; - Assert.Null(EnumerablePartition(source).ElementAtOrDefault(1)); - Assert.Null(EnumerablePartition(source).ElementAtOrDefault(-1)); - Assert.Null(EnumerablePartition(source).ElementAtOrDefault(new Index(1))); - Assert.Null(EnumerablePartition(source).ElementAtOrDefault(^1)); + 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(EnumerablePartition(source).ElementAtOrDefault(0)); - Assert.Null(EnumerablePartition(source).ElementAtOrDefault(new Index(0))); - Assert.Null(EnumerablePartition(source).ElementAtOrDefault(^0)); + Assert.Null(EnumerablePartitionOrEmpty(source).ElementAtOrDefault(0)); + Assert.Null(EnumerablePartitionOrEmpty(source).ElementAtOrDefault(new Index(0))); + Assert.Null(EnumerablePartitionOrEmpty(source).ElementAtOrDefault(^0)); - Assert.Null(EnumerablePartition(source).ElementAtOrDefault(int.MinValue)); - Assert.Null(EnumerablePartition(source).ElementAtOrDefault(^int.MaxValue)); + Assert.Null(EnumerablePartitionOrEmpty(source).ElementAtOrDefault(int.MinValue)); + Assert.Null(EnumerablePartitionOrEmpty(source).ElementAtOrDefault(^int.MaxValue)); - Assert.Null(EnumerablePartition(source).ElementAtOrDefault(int.MaxValue)); - Assert.Null(EnumerablePartition(source).ElementAtOrDefault(new Index(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 08118afcd5d716..e3a3df6ad49fee 100644 --- a/src/libraries/System.Linq/tests/ElementAtTests.cs +++ b/src/libraries/System.Linq/tests/ElementAtTests.cs @@ -217,30 +217,30 @@ public void NonEmptySource_Consistency_ListPartition() { int[] source = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; - Assert.Equal(5, ListPartition(source).ElementAt(5)); - Assert.Equal(5, ListPartition(source).ElementAt(new Index(5))); - Assert.Equal(5, ListPartition(source).ElementAt(^5)); + 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, ListPartition(source).ElementAt(0)); - Assert.Equal(0, ListPartition(source).ElementAt(new Index(0))); - Assert.Equal(0, ListPartition(source).ElementAt(^10)); + 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, ListPartition(source).ElementAt(9)); - Assert.Equal(9, ListPartition(source).ElementAt(new Index(9))); - Assert.Equal(9, ListPartition(source).ElementAt(^1)); + Assert.Equal(9, ListPartitionOrEmpty(source).ElementAt(9)); + Assert.Equal(9, ListPartitionOrEmpty(source).ElementAt(new Index(9))); + Assert.Equal(9, ListPartitionOrEmpty(source).ElementAt(^1)); - AssertExtensions.Throws("index", () => ListPartition(source).ElementAt(-1)); - AssertExtensions.Throws("index", () => ListPartition(source).ElementAt(^11)); + AssertExtensions.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(-1)); + AssertExtensions.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(^11)); - AssertExtensions.Throws("index", () => ListPartition(source).ElementAt(10)); - AssertExtensions.Throws("index", () => ListPartition(source).ElementAt(new Index(10))); - AssertExtensions.Throws("index", () => ListPartition(source).ElementAt(^0)); + AssertExtensions.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(10)); + AssertExtensions.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(new Index(10))); + AssertExtensions.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(^0)); - AssertExtensions.Throws("index", () => ListPartition(source).ElementAt(int.MinValue)); - AssertExtensions.Throws("index", () => ListPartition(source).ElementAt(^int.MaxValue)); + AssertExtensions.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(int.MinValue)); + AssertExtensions.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(^int.MaxValue)); - AssertExtensions.Throws("index", () => ListPartition(source).ElementAt(int.MaxValue)); - AssertExtensions.Throws("index", () => ListPartition(source).ElementAt(new Index(int.MaxValue))); + AssertExtensions.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(int.MaxValue)); + AssertExtensions.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(new Index(int.MaxValue))); } [Fact] @@ -248,30 +248,30 @@ public void NonEmptySource_Consistency_EnumerablePartition() { int[] source = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; - Assert.Equal(5, EnumerablePartition(source).ElementAt(5)); - Assert.Equal(5, EnumerablePartition(source).ElementAt(new Index(5))); - Assert.Equal(5, EnumerablePartition(source).ElementAt(^5)); + 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, EnumerablePartition(source).ElementAt(0)); - Assert.Equal(0, EnumerablePartition(source).ElementAt(new Index(0))); - Assert.Equal(0, EnumerablePartition(source).ElementAt(^10)); + 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, EnumerablePartition(source).ElementAt(9)); - Assert.Equal(9, EnumerablePartition(source).ElementAt(new Index(9))); - Assert.Equal(9, EnumerablePartition(source).ElementAt(^1)); + Assert.Equal(9, EnumerablePartitionOrEmpty(source).ElementAt(9)); + Assert.Equal(9, EnumerablePartitionOrEmpty(source).ElementAt(new Index(9))); + Assert.Equal(9, EnumerablePartitionOrEmpty(source).ElementAt(^1)); - AssertExtensions.Throws("index", () => EnumerablePartition(source).ElementAt(-1)); - AssertExtensions.Throws("index", () => EnumerablePartition(source).ElementAt(^11)); + AssertExtensions.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(-1)); + AssertExtensions.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(^11)); - AssertExtensions.Throws("index", () => EnumerablePartition(source).ElementAt(10)); - AssertExtensions.Throws("index", () => EnumerablePartition(source).ElementAt(new Index(10))); - AssertExtensions.Throws("index", () => EnumerablePartition(source).ElementAt(^0)); + AssertExtensions.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(10)); + AssertExtensions.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(new Index(10))); + AssertExtensions.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(^0)); - AssertExtensions.Throws("index", () => EnumerablePartition(source).ElementAt(int.MinValue)); - AssertExtensions.Throws("index", () => EnumerablePartition(source).ElementAt(^int.MaxValue)); + AssertExtensions.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(int.MinValue)); + AssertExtensions.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(^int.MaxValue)); - AssertExtensions.Throws("index", () => EnumerablePartition(source).ElementAt(int.MaxValue)); - AssertExtensions.Throws("index", () => EnumerablePartition(source).ElementAt(new Index(int.MaxValue))); + AssertExtensions.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(int.MaxValue)); + AssertExtensions.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(new Index(int.MaxValue))); } [Fact] @@ -383,20 +383,20 @@ public void EmptySource_Consistency_ListPartition() { int[] source = { }; - AssertExtensions.Throws("index", () => ListPartition(source).ElementAt(1)); - AssertExtensions.Throws("index", () => ListPartition(source).ElementAt(-1)); - AssertExtensions.Throws("index", () => ListPartition(source).ElementAt(new Index(1))); - AssertExtensions.Throws("index", () => ListPartition(source).ElementAt(^1)); + AssertExtensions.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(1)); + AssertExtensions.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(-1)); + AssertExtensions.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(new Index(1))); + AssertExtensions.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(^1)); - AssertExtensions.Throws("index", () => ListPartition(source).ElementAt(0)); - AssertExtensions.Throws("index", () => ListPartition(source).ElementAt(new Index(0))); - AssertExtensions.Throws("index", () => ListPartition(source).ElementAt(^0)); + AssertExtensions.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(0)); + AssertExtensions.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(new Index(0))); + AssertExtensions.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(^0)); - AssertExtensions.Throws("index", () => ListPartition(source).ElementAt(int.MinValue)); - AssertExtensions.Throws("index", () => ListPartition(source).ElementAt(^int.MaxValue)); + AssertExtensions.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(int.MinValue)); + AssertExtensions.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(^int.MaxValue)); - AssertExtensions.Throws("index", () => ListPartition(source).ElementAt(int.MaxValue)); - AssertExtensions.Throws("index", () => ListPartition(source).ElementAt(new Index(int.MaxValue))); + AssertExtensions.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(int.MaxValue)); + AssertExtensions.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(new Index(int.MaxValue))); } [Fact] @@ -404,20 +404,20 @@ public void EmptySource_Consistency_EnumerablePartition() { int[] source = { }; - AssertExtensions.Throws("index", () => EnumerablePartition(source).ElementAt(1)); - AssertExtensions.Throws("index", () => EnumerablePartition(source).ElementAt(-1)); - AssertExtensions.Throws("index", () => EnumerablePartition(source).ElementAt(new Index(1))); - AssertExtensions.Throws("index", () => EnumerablePartition(source).ElementAt(^1)); + AssertExtensions.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(1)); + AssertExtensions.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(-1)); + AssertExtensions.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(new Index(1))); + AssertExtensions.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(^1)); - AssertExtensions.Throws("index", () => EnumerablePartition(source).ElementAt(0)); - AssertExtensions.Throws("index", () => EnumerablePartition(source).ElementAt(new Index(0))); - AssertExtensions.Throws("index", () => EnumerablePartition(source).ElementAt(^0)); + AssertExtensions.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(0)); + AssertExtensions.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(new Index(0))); + AssertExtensions.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(^0)); - AssertExtensions.Throws("index", () => EnumerablePartition(source).ElementAt(int.MinValue)); - AssertExtensions.Throws("index", () => EnumerablePartition(source).ElementAt(^int.MaxValue)); + AssertExtensions.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(int.MinValue)); + AssertExtensions.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(^int.MaxValue)); - AssertExtensions.Throws("index", () => EnumerablePartition(source).ElementAt(int.MaxValue)); - AssertExtensions.Throws("index", () => EnumerablePartition(source).ElementAt(new Index(int.MaxValue))); + AssertExtensions.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(int.MaxValue)); + AssertExtensions.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(new Index(int.MaxValue))); } [Fact] diff --git a/src/libraries/System.Linq/tests/EnumerableTests.cs b/src/libraries/System.Linq/tests/EnumerableTests.cs index f5a865fe5b18db..9a46e4c571598b 100644 --- a/src/libraries/System.Linq/tests/EnumerableTests.cs +++ b/src/libraries/System.Linq/tests/EnumerableTests.cs @@ -253,17 +253,21 @@ protected static T[] Repeat(Func factory, int count) return results; } - protected static IEnumerable ListPartition(IList source) + protected static IEnumerable ListPartitionOrEmpty(IList source) // Or Empty { - var listPartition = source.Skip(0); // new ListPartition(sourceList, count, int.MaxValue) - Assert.True(listPartition.GetType().Name.Contains(nameof(ListPartition), StringComparison.InvariantCulture)); + var listPartition = source.Skip(0); + Assert.True( + listPartition.GetType().Name.Contains("ListPartition", StringComparison.InvariantCulture) + || listPartition.GetType().Name.Contains("EmptyPartition", StringComparison.InvariantCulture)); return listPartition; } - protected static IEnumerable EnumerablePartition(IEnumerable source) + protected static IEnumerable EnumerablePartitionOrEmpty(IEnumerable source) // Or Empty { - var enumerablePartition = ForceNotCollection(source).Skip(0); // new EnumerablePartition(source, count, -1) - Assert.True(enumerablePartition.GetType().Name.Contains(nameof(EnumerablePartition), StringComparison.InvariantCulture)); + var enumerablePartition = ForceNotCollection(source).Skip(0); + Assert.True( + enumerablePartition.GetType().Name.Contains("EnumerablePartition", StringComparison.InvariantCulture) + || enumerablePartition.GetType().Name.Contains("EmptyPartition", StringComparison.InvariantCulture)); return enumerablePartition; } diff --git a/src/libraries/System.Linq/tests/TakeTests.cs b/src/libraries/System.Linq/tests/TakeTests.cs index a3d440188b83ff..e4222966f3d209 100644 --- a/src/libraries/System.Linq/tests/TakeTests.cs +++ b/src/libraries/System.Linq/tests/TakeTests.cs @@ -1401,36 +1401,36 @@ public void OutOfBoundNoExceptionListPartition() { var source = new[] { 1, 2, 3, 4, 5 }; - Assert.Equal(source, ListPartition(source).Take(0..6)); - Assert.Equal(source, ListPartition(source).Take(0..int.MaxValue)); - - Assert.Equal(new int[] { 1, 2, 3, 4 }, ListPartition(source).Take(^10..4)); - Assert.Equal(new int[] { 1, 2, 3, 4 }, ListPartition(source).Take(^int.MaxValue..4)); - Assert.Equal(source, ListPartition(source).Take(^10..6)); - Assert.Equal(source, ListPartition(source).Take(^int.MaxValue..6)); - Assert.Equal(source, ListPartition(source).Take(^10..int.MaxValue)); - Assert.Equal(source, ListPartition(source).Take(^int.MaxValue..int.MaxValue)); - - Assert.Empty(ListPartition(source).Take(0..^6)); - Assert.Empty(ListPartition(source).Take(0..^int.MaxValue)); - Assert.Empty(ListPartition(source).Take(4..^6)); - Assert.Empty(ListPartition(source).Take(4..^int.MaxValue)); - Assert.Empty(ListPartition(source).Take(6..^6)); - Assert.Empty(ListPartition(source).Take(6..^int.MaxValue)); - Assert.Empty(ListPartition(source).Take(int.MaxValue..^6)); - Assert.Empty(ListPartition(source).Take(int.MaxValue..^int.MaxValue)); - - Assert.Equal(new int[] { 1, 2, 3, 4 }, ListPartition(source).Take(^10..^1)); - Assert.Equal(new int[] { 1, 2, 3, 4 }, ListPartition(source).Take(^int.MaxValue..^1)); - Assert.Empty(ListPartition(source).Take(^0..^6)); - Assert.Empty(ListPartition(source).Take(^1..^6)); - Assert.Empty(ListPartition(source).Take(^6..^6)); - Assert.Empty(ListPartition(source).Take(^10..^6)); - Assert.Empty(ListPartition(source).Take(^int.MaxValue..^6)); - Assert.Empty(ListPartition(source).Take(^0..^int.MaxValue)); - Assert.Empty(ListPartition(source).Take(^1..^int.MaxValue)); - Assert.Empty(ListPartition(source).Take(^6..^int.MaxValue)); - Assert.Empty(ListPartition(source).Take(^int.MaxValue..^int.MaxValue)); + 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] @@ -1438,36 +1438,36 @@ public void OutOfBoundNoExceptionEnumerablePartition() { var source = new[] { 1, 2, 3, 4, 5 }; - Assert.Equal(source, EnumerablePartition(source).Take(0..6)); - Assert.Equal(source, EnumerablePartition(source).Take(0..int.MaxValue)); - - Assert.Equal(new int[] { 1, 2, 3, 4 }, EnumerablePartition(source).Take(^10..4)); - Assert.Equal(new int[] { 1, 2, 3, 4 }, EnumerablePartition(source).Take(^int.MaxValue..4)); - Assert.Equal(source, EnumerablePartition(source).Take(^10..6)); - Assert.Equal(source, EnumerablePartition(source).Take(^int.MaxValue..6)); - Assert.Equal(source, EnumerablePartition(source).Take(^10..int.MaxValue)); - Assert.Equal(source, EnumerablePartition(source).Take(^int.MaxValue..int.MaxValue)); - - Assert.Empty(EnumerablePartition(source).Take(0..^6)); - Assert.Empty(EnumerablePartition(source).Take(0..^int.MaxValue)); - Assert.Empty(EnumerablePartition(source).Take(4..^6)); - Assert.Empty(EnumerablePartition(source).Take(4..^int.MaxValue)); - Assert.Empty(EnumerablePartition(source).Take(6..^6)); - Assert.Empty(EnumerablePartition(source).Take(6..^int.MaxValue)); - Assert.Empty(EnumerablePartition(source).Take(int.MaxValue..^6)); - Assert.Empty(EnumerablePartition(source).Take(int.MaxValue..^int.MaxValue)); - - Assert.Equal(new int[] { 1, 2, 3, 4 }, EnumerablePartition(source).Take(^10..^1)); - Assert.Equal(new int[] { 1, 2, 3, 4 }, EnumerablePartition(source).Take(^int.MaxValue..^1)); - Assert.Empty(EnumerablePartition(source).Take(^0..^6)); - Assert.Empty(EnumerablePartition(source).Take(^1..^6)); - Assert.Empty(EnumerablePartition(source).Take(^6..^6)); - Assert.Empty(EnumerablePartition(source).Take(^10..^6)); - Assert.Empty(EnumerablePartition(source).Take(^int.MaxValue..^6)); - Assert.Empty(EnumerablePartition(source).Take(^0..^int.MaxValue)); - Assert.Empty(EnumerablePartition(source).Take(^1..^int.MaxValue)); - Assert.Empty(EnumerablePartition(source).Take(^6..^int.MaxValue)); - Assert.Empty(EnumerablePartition(source).Take(^int.MaxValue..^int.MaxValue)); + 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] @@ -1624,44 +1624,44 @@ 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], ListPartition(source).Take(^9..5)); - Assert.Equal(source[2..7], ListPartition(source).Take(2..7)); - Assert.Equal(source[2..^4], ListPartition(source).Take(2..^4)); - Assert.Equal(source[^7..^4], ListPartition(source).Take(^7..^4)); + 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..], ListPartition(source).Take(^9..)); - Assert.Equal(source[2..], ListPartition(source).Take(2..)); - Assert.Equal(source[..^4], ListPartition(source).Take(..^4)); - Assert.Equal(source[..6], ListPartition(source).Take(..6)); + 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[..], ListPartition(source).Take(..)); + Assert.Equal(source[..], ListPartitionOrEmpty(source).Take(..)); // Single element in the middle. - Assert.Equal(source[^9..2], ListPartition(source).Take(^9..2)); - Assert.Equal(source[2..3], ListPartition(source).Take(2..3)); - Assert.Equal(source[2..^7], ListPartition(source).Take(2..^7)); - Assert.Equal(source[^5..^4], ListPartition(source).Take(^5..^4)); + 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], ListPartition(source).Take(^10..1)); - Assert.Equal(source[0..1], ListPartition(source).Take(0..1)); - Assert.Equal(source[0..^9], ListPartition(source).Take(0..^9)); - Assert.Equal(source[^10..^9], ListPartition(source).Take(^10..^9)); + 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], ListPartition(source).Take(^1..10)); - Assert.Equal(source[9..10], ListPartition(source).Take(9..10)); - Assert.Equal(source[9..^0], ListPartition(source).Take(9..^0)); - Assert.Equal(source[^1..^0], ListPartition(source).Take(^1..^0)); + 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], ListPartition(source).Take(3..3)); - Assert.Equal(source[6..^4], ListPartition(source).Take(6..^4)); - Assert.Equal(source[3..^7], ListPartition(source).Take(3..^7)); - Assert.Equal(source[^3..7], ListPartition(source).Take(^3..7)); - Assert.Equal(source[^6..^6], ListPartition(source).Take(^6..^6)); + 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] @@ -1670,44 +1670,44 @@ 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], EnumerablePartition(source).Take(^9..5)); - Assert.Equal(source[2..7], EnumerablePartition(source).Take(2..7)); - Assert.Equal(source[2..^4], EnumerablePartition(source).Take(2..^4)); - Assert.Equal(source[^7..^4], EnumerablePartition(source).Take(^7..^4)); + 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..], EnumerablePartition(source).Take(^9..)); - Assert.Equal(source[2..], EnumerablePartition(source).Take(2..)); - Assert.Equal(source[..^4], EnumerablePartition(source).Take(..^4)); - Assert.Equal(source[..6], EnumerablePartition(source).Take(..6)); + 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[..], EnumerablePartition(source).Take(..)); + Assert.Equal(source[..], EnumerablePartitionOrEmpty(source).Take(..)); // Single element in the middle. - Assert.Equal(source[^9..2], EnumerablePartition(source).Take(^9..2)); - Assert.Equal(source[2..3], EnumerablePartition(source).Take(2..3)); - Assert.Equal(source[2..^7], EnumerablePartition(source).Take(2..^7)); - Assert.Equal(source[^5..^4], EnumerablePartition(source).Take(^5..^4)); + 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], EnumerablePartition(source).Take(^10..1)); - Assert.Equal(source[0..1], EnumerablePartition(source).Take(0..1)); - Assert.Equal(source[0..^9], EnumerablePartition(source).Take(0..^9)); - Assert.Equal(source[^10..^9], EnumerablePartition(source).Take(^10..^9)); + 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], EnumerablePartition(source).Take(^1..10)); - Assert.Equal(source[9..10], EnumerablePartition(source).Take(9..10)); - Assert.Equal(source[9..^0], EnumerablePartition(source).Take(9..^0)); - Assert.Equal(source[^1..^0], EnumerablePartition(source).Take(^1..^0)); + 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], EnumerablePartition(source).Take(3..3)); - Assert.Equal(source[6..^4], EnumerablePartition(source).Take(6..^4)); - Assert.Equal(source[3..^7], EnumerablePartition(source).Take(3..^7)); - Assert.Equal(source[^3..7], EnumerablePartition(source).Take(^3..7)); - Assert.Equal(source[^6..^6], EnumerablePartition(source).Take(^6..^6)); + 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] @@ -1737,10 +1737,10 @@ public void NonEmptySource_DoNotThrowException_ListPartition() { int[] source = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; - Assert.Empty(ListPartition(source).Take(3..2)); - Assert.Empty(ListPartition(source).Take(6..^5)); - Assert.Empty(ListPartition(source).Take(3..^8)); - Assert.Empty(ListPartition(source).Take(^6..^7)); + 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] @@ -1748,10 +1748,10 @@ public void NonEmptySource_DoNotThrowException_EnumerablePartition() { int[] source = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; - Assert.Empty(EnumerablePartition(source).Take(3..2)); - Assert.Empty(EnumerablePartition(source).Take(6..^5)); - Assert.Empty(EnumerablePartition(source).Take(3..^8)); - Assert.Empty(EnumerablePartition(source).Take(^6..^7)); + 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] @@ -1864,50 +1864,50 @@ public void EmptySource_DoNotThrowException_ListPartition() int[] source = { }; // Multiple elements in the middle. - Assert.Empty(ListPartition(source).Take(^9..5)); - Assert.Empty(ListPartition(source).Take(2..7)); - Assert.Empty(ListPartition(source).Take(2..^4)); - Assert.Empty(ListPartition(source).Take(^7..^4)); + 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(ListPartition(source).Take(^9..)); - Assert.Empty(ListPartition(source).Take(2..)); - Assert.Empty(ListPartition(source).Take(..^4)); - Assert.Empty(ListPartition(source).Take(..6)); + 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[..], ListPartition(source).Take(..)); + Assert.Equal(source[..], ListPartitionOrEmpty(source).Take(..)); // Single element in the middle. - Assert.Empty(ListPartition(source).Take(^9..2)); - Assert.Empty(ListPartition(source).Take(2..3)); - Assert.Empty(ListPartition(source).Take(2..^7)); - Assert.Empty(ListPartition(source).Take(^5..^4)); + 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(ListPartition(source).Take(^10..1)); - Assert.Empty(ListPartition(source).Take(0..1)); - Assert.Empty(ListPartition(source).Take(0..^9)); - Assert.Empty(ListPartition(source).Take(^10..^9)); + 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(ListPartition(source).Take(^1..^10)); - Assert.Empty(ListPartition(source).Take(9..10)); - Assert.Empty(ListPartition(source).Take(9..^9)); - Assert.Empty(ListPartition(source).Take(^1..^9)); + 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(ListPartition(source).Take(3..3)); - Assert.Empty(ListPartition(source).Take(6..^4)); - Assert.Empty(ListPartition(source).Take(3..^7)); - Assert.Empty(ListPartition(source).Take(^3..7)); - Assert.Empty(ListPartition(source).Take(^6..^6)); + 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(ListPartition(source).Take(3..2)); - Assert.Empty(ListPartition(source).Take(6..^5)); - Assert.Empty(ListPartition(source).Take(3..^8)); - Assert.Empty(ListPartition(source).Take(^6..^7)); + 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] @@ -1916,50 +1916,50 @@ public void EmptySource_DoNotThrowException_EnumerablePartition() int[] source = { }; // Multiple elements in the middle. - Assert.Empty(EnumerablePartition(source).Take(^9..5)); - Assert.Empty(EnumerablePartition(source).Take(2..7)); - Assert.Empty(EnumerablePartition(source).Take(2..^4)); - Assert.Empty(EnumerablePartition(source).Take(^7..^4)); + 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(EnumerablePartition(source).Take(^9..)); - Assert.Empty(EnumerablePartition(source).Take(2..)); - Assert.Empty(EnumerablePartition(source).Take(..^4)); - Assert.Empty(EnumerablePartition(source).Take(..6)); + 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[..], EnumerablePartition(source).Take(..)); + Assert.Equal(source[..], EnumerablePartitionOrEmpty(source).Take(..)); // Single element in the middle. - Assert.Empty(EnumerablePartition(source).Take(^9..2)); - Assert.Empty(EnumerablePartition(source).Take(2..3)); - Assert.Empty(EnumerablePartition(source).Take(2..^7)); - Assert.Empty(EnumerablePartition(source).Take(^5..^4)); + 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(EnumerablePartition(source).Take(^10..1)); - Assert.Empty(EnumerablePartition(source).Take(0..1)); - Assert.Empty(EnumerablePartition(source).Take(0..^9)); - Assert.Empty(EnumerablePartition(source).Take(^10..^9)); + 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(EnumerablePartition(source).Take(^1..^10)); - Assert.Empty(EnumerablePartition(source).Take(9..10)); - Assert.Empty(EnumerablePartition(source).Take(9..^9)); - Assert.Empty(EnumerablePartition(source).Take(^1..^9)); + 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(EnumerablePartition(source).Take(3..3)); - Assert.Empty(EnumerablePartition(source).Take(6..^4)); - Assert.Empty(EnumerablePartition(source).Take(3..^7)); - Assert.Empty(EnumerablePartition(source).Take(^3..7)); - Assert.Empty(EnumerablePartition(source).Take(^6..^6)); + 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(EnumerablePartition(source).Take(3..2)); - Assert.Empty(EnumerablePartition(source).Take(6..^5)); - Assert.Empty(EnumerablePartition(source).Take(3..^8)); - Assert.Empty(EnumerablePartition(source).Take(^6..^7)); + 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)); } } } From fe61d5916540036c46bd602cbc5ddae7f0dfa809 Mon Sep 17 00:00:00 2001 From: Dixin Date: Sun, 14 Feb 2021 09:26:53 -0800 Subject: [PATCH 24/35] Implement dotnet/runtime#28776: LINQ APIs for index and range. --- src/libraries/System.Linq/tests/EnumerableTests.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/libraries/System.Linq/tests/EnumerableTests.cs b/src/libraries/System.Linq/tests/EnumerableTests.cs index 9a46e4c571598b..16869e2654a056 100644 --- a/src/libraries/System.Linq/tests/EnumerableTests.cs +++ b/src/libraries/System.Linq/tests/EnumerableTests.cs @@ -256,18 +256,12 @@ protected static T[] Repeat(Func factory, int count) protected static IEnumerable ListPartitionOrEmpty(IList source) // Or Empty { var listPartition = source.Skip(0); - Assert.True( - listPartition.GetType().Name.Contains("ListPartition", StringComparison.InvariantCulture) - || listPartition.GetType().Name.Contains("EmptyPartition", StringComparison.InvariantCulture)); return listPartition; } protected static IEnumerable EnumerablePartitionOrEmpty(IEnumerable source) // Or Empty { var enumerablePartition = ForceNotCollection(source).Skip(0); - Assert.True( - enumerablePartition.GetType().Name.Contains("EnumerablePartition", StringComparison.InvariantCulture) - || enumerablePartition.GetType().Name.Contains("EmptyPartition", StringComparison.InvariantCulture)); return enumerablePartition; } From 2ca8ca61b073b77159f23c9d885fcf72d8d29c6d Mon Sep 17 00:00:00 2001 From: Dixin Date: Mon, 15 Feb 2021 15:32:12 -0800 Subject: [PATCH 25/35] Implement dotnet/runtime#28776: LINQ APIs for index and range. --- .../System.Linq/src/System/Linq/ElementAt.cs | 211 ++++++++---------- 1 file changed, 96 insertions(+), 115 deletions(-) diff --git a/src/libraries/System.Linq/src/System/Linq/ElementAt.cs b/src/libraries/System.Linq/src/System/Linq/ElementAt.cs index 844824b65682ae..58bbac1782f5c2 100644 --- a/src/libraries/System.Linq/src/System/Linq/ElementAt.cs +++ b/src/libraries/System.Linq/src/System/Linq/ElementAt.cs @@ -17,25 +17,12 @@ public static TSource ElementAt(this IEnumerable source, int i ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source); } - if (source is IPartition partition) + if (!TryGetElementAt(source, index, isIndexFromEnd: false, out TSource? element)) { - TSource? element = partition.TryGetElementAt(index, out bool found); - if (found) - { - return element!; - } - } - else if (source is IList list) - { - return list[index]; - } - else if (TryGetElement(source, index, out TSource? element)) - { - return element; + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); } - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); - return default; + return element; } /// Returns the element at a specified index in a sequence. @@ -55,12 +42,7 @@ public static TSource ElementAt(this IEnumerable source, Index ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source); } - if (!index.IsFromEnd) - { - return source.ElementAt(index.Value); - } - - if (!TryGetElementFromEnd(source, index.Value, out TSource? element)) + if (!TryGetElementAt(source, index.Value, index.IsFromEnd, out TSource? element)) { ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); } @@ -75,24 +57,8 @@ public static TSource ElementAt(this IEnumerable source, Index ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source); } - if (source is IPartition partition) - { - return partition.TryGetElementAt(index, out bool _); - } - - if (source is IList list) - { - if (index >= 0 && index < list.Count) - { - return list[index]; - } - } - else if (TryGetElement(source, index, out TSource? element)) - { - return element; - } - - return default; + TryGetElementAt(source, index, isIndexFromEnd: false, 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. @@ -112,125 +78,140 @@ public static TSource ElementAt(this IEnumerable source, Index ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source); } - if (!index.IsFromEnd) - { - return source.ElementAtOrDefault(index.Value); - } - - TryGetElementFromEnd(source, index.Value, out TSource? element); + TryGetElementAt(source, index.Value, index.IsFromEnd, out TSource? element); return element; } - private static bool TryGetElement(IEnumerable source, int index, [MaybeNullWhen(false)] out TSource element) + private static bool TryGetElementAt(IEnumerable source, int index, bool isIndexFromEnd, [MaybeNullWhen(false)] out TSource element) { Debug.Assert(source != null); - if (index >= 0) + element = default; + if (index < 0 || (isIndexFromEnd && index == 0)) { - using IEnumerator e = source.GetEnumerator(); - while (e.MoveNext()) + return false; + } + + if (source is IList list) + { + int listCount = list.Count; + if (listCount > 0) { - if (index == 0) + if (isIndexFromEnd) { - element = e.Current; - return true; + index = listCount - index; + if (index < 0) + { + return false; + } } - index--; + if (index < listCount) + { + element = list[index]; + return true; + } } - } - element = default; - return false; - } - - private static bool TryGetElementFromEnd(IEnumerable source, int indexFromEnd, [MaybeNullWhen(false)] out TSource element) - { - Debug.Assert(source != null); - Debug.Assert(indexFromEnd >= 0); - - element = default; - if (indexFromEnd == 0) - { return false; } - if (source is IPartition partition) + int count = -1; + if (source is IIListProvider listProvider) { - int count = partition.GetCount(onlyIfCheap: true); - if (count == 0) + if (source is IPartition partition) { - return false; - } - - if (count > 0) - { - if (indexFromEnd <= count) + if (isIndexFromEnd) + { + count = listProvider.GetCount(onlyIfCheap: true); + if (count > 0) + { + element = partition.TryGetElementAt(count - index, out bool found); + return found; + } + } + else { - element = partition.TryGetElementAt(count - indexFromEnd, out bool found); + element = partition.TryGetElementAt(index, out bool found); return found; } - - return false; } - } - else if (source is IList list) - { - int count = list.Count; - if (count > 0 && indexFromEnd <= count) + else { - element = list[count - indexFromEnd]; - return true; + count = listProvider.GetCount(onlyIfCheap: true); } - - return false; } else if (source is ICollection genericCollection) { - int count = genericCollection.Count; - return count > 0 && TryGetElement(source, count - indexFromEnd, out element); + count = genericCollection.Count; + } + else if (source is ICollection collection) + { + count = collection.Count; } - else if (source is IIListProvider listProvider) + + if (count == 0) { - int count = listProvider.GetCount(onlyIfCheap: true); - if (count == 0) + return false; + } + + if (count > 0) + { + if (isIndexFromEnd) { - return false; + index = count - index; + if (index < 0) + { + return false; + } + + isIndexFromEnd = false; } - if (count > 0) + if (index >= count) { - return TryGetElement(source, count - indexFromEnd, out element); + return false; } } - else if (source is ICollection collection) - { - int count = collection.Count; - return count > 0 && TryGetElement(source, count - indexFromEnd, out element); - } using IEnumerator e = source.GetEnumerator(); - if (!e.MoveNext()) + if (isIndexFromEnd) { - return false; - } - - Queue queue = new(); - queue.Enqueue(e.Current); - while (e.MoveNext()) - { - if (queue.Count == indexFromEnd) + if (!e.MoveNext()) { - queue.Dequeue(); + return false; } + Queue queue = new(); queue.Enqueue(e.Current); - } + while (e.MoveNext()) + { + if (queue.Count == index) + { + queue.Dequeue(); + } - if (queue.Count == indexFromEnd) + queue.Enqueue(e.Current); + } + + if (queue.Count == index) + { + element = queue.Dequeue(); + return true; + } + } + else { - element = queue.Dequeue(); - return true; + while (e.MoveNext()) + { + if (index == 0) + { + element = e.Current; + return true; + } + + index--; + } } return false; From 6374006cae91f334b6f8c7f625e438ff9fc721d6 Mon Sep 17 00:00:00 2001 From: Dixin Date: Mon, 15 Feb 2021 16:23:53 -0800 Subject: [PATCH 26/35] Implement dotnet/runtime#28776: LINQ APIs for index and range. --- src/libraries/System.Linq/src/System/Linq/ElementAt.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libraries/System.Linq/src/System/Linq/ElementAt.cs b/src/libraries/System.Linq/src/System/Linq/ElementAt.cs index 58bbac1782f5c2..f057dc8020cfcb 100644 --- a/src/libraries/System.Linq/src/System/Linq/ElementAt.cs +++ b/src/libraries/System.Linq/src/System/Linq/ElementAt.cs @@ -123,7 +123,7 @@ private static bool TryGetElementAt(IEnumerable source, int in { if (isIndexFromEnd) { - count = listProvider.GetCount(onlyIfCheap: true); + count = partition.GetCount(onlyIfCheap: true); if (count > 0) { element = partition.TryGetElementAt(count - index, out bool found); @@ -141,9 +141,9 @@ private static bool TryGetElementAt(IEnumerable source, int in count = listProvider.GetCount(onlyIfCheap: true); } } - else if (source is ICollection genericCollection) + else if (source is ICollection collectionoft) { - count = genericCollection.Count; + count = collectionoft.Count; } else if (source is ICollection collection) { From 36e1f9596f2aa4c2f13e278d79393f84e22ae8d6 Mon Sep 17 00:00:00 2001 From: Dixin Date: Tue, 16 Feb 2021 16:49:37 -0800 Subject: [PATCH 27/35] Implement dotnet/runtime#28776: LINQ APIs for index and range. Update ElementAt, keep the original behavior. --- .../System.Linq/src/System/Linq/ElementAt.cs | 198 ++++++++---------- 1 file changed, 84 insertions(+), 114 deletions(-) diff --git a/src/libraries/System.Linq/src/System/Linq/ElementAt.cs b/src/libraries/System.Linq/src/System/Linq/ElementAt.cs index f057dc8020cfcb..e8e662b95c3bb3 100644 --- a/src/libraries/System.Linq/src/System/Linq/ElementAt.cs +++ b/src/libraries/System.Linq/src/System/Linq/ElementAt.cs @@ -17,12 +17,25 @@ public static TSource ElementAt(this IEnumerable source, int i ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source); } - if (!TryGetElementAt(source, index, isIndexFromEnd: false, out TSource? element)) + if (source is IPartition partition) { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); + TSource? element = partition.TryGetElementAt(index, out bool found); + if (found) + { + return element!; + } + } + else if (source is IList list) + { + return list[index]; + } + else if (TryGetElement(source, index, out TSource? element)) + { + return element; } - return element; + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); + return default; } /// Returns the element at a specified index in a sequence. @@ -42,7 +55,17 @@ public static TSource ElementAt(this IEnumerable source, Index ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source); } - if (!TryGetElementAt(source, index.Value, index.IsFromEnd, out TSource? element)) + 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); } @@ -57,8 +80,24 @@ public static TSource ElementAt(this IEnumerable source, Index ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source); } - TryGetElementAt(source, index, isIndexFromEnd: false, out TSource? element); - return element; + if (source is IPartition partition) + { + return partition.TryGetElementAt(index, out bool _); + } + + if (source is IList list) + { + if (index >= 0 && index < list.Count) + { + return list[index]; + } + } + else if (TryGetElement(source, index, out TSource? element)) + { + return element; + } + + return default; } /// Returns the element at a specified index in a sequence or a default value if the index is out of range. @@ -78,142 +117,73 @@ public static TSource ElementAt(this IEnumerable source, Index ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source); } - TryGetElementAt(source, index.Value, index.IsFromEnd, out TSource? element); + 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 TryGetElementAt(IEnumerable source, int index, bool isIndexFromEnd, [MaybeNullWhen(false)] out TSource element) + private static bool TryGetElement(IEnumerable source, int index, [MaybeNullWhen(false)] out TSource element) { Debug.Assert(source != null); - element = default; - if (index < 0 || (isIndexFromEnd && index == 0)) + if (index >= 0) { - return false; - } - - if (source is IList list) - { - int listCount = list.Count; - if (listCount > 0) + using IEnumerator e = source.GetEnumerator(); + while (e.MoveNext()) { - if (isIndexFromEnd) - { - index = listCount - index; - if (index < 0) - { - return false; - } - } - - if (index < listCount) + if (index == 0) { - element = list[index]; + element = e.Current; return true; } - } - - return false; - } - int count = -1; - if (source is IIListProvider listProvider) - { - if (source is IPartition partition) - { - if (isIndexFromEnd) - { - count = partition.GetCount(onlyIfCheap: true); - if (count > 0) - { - element = partition.TryGetElementAt(count - index, out bool found); - return found; - } - } - else - { - element = partition.TryGetElementAt(index, out bool found); - return found; - } - } - else - { - count = listProvider.GetCount(onlyIfCheap: true); + index--; } } - else if (source is ICollection collectionoft) - { - count = collectionoft.Count; - } - else if (source is ICollection collection) - { - count = collection.Count; - } - - if (count == 0) - { - return false; - } - - if (count > 0) - { - if (isIndexFromEnd) - { - index = count - index; - if (index < 0) - { - return false; - } - isIndexFromEnd = false; - } + element = default; + return false; + } - if (index >= count) - { - return false; - } - } + private static bool TryGetElementFromEnd(IEnumerable source, int indexFromEnd, [MaybeNullWhen(false)] out TSource element) + { + Debug.Assert(source != null); - using IEnumerator e = source.GetEnumerator(); - if (isIndexFromEnd) + if (indexFromEnd > 0) { - if (!e.MoveNext()) - { - return false; - } - - Queue queue = new(); - queue.Enqueue(e.Current); - while (e.MoveNext()) + using IEnumerator e = source.GetEnumerator(); + if (e.MoveNext()) { - if (queue.Count == index) + Queue queue = new(); + queue.Enqueue(e.Current); + while (e.MoveNext()) { - queue.Dequeue(); - } + if (queue.Count == indexFromEnd) + { + queue.Dequeue(); + } - queue.Enqueue(e.Current); - } + queue.Enqueue(e.Current); + } - if (queue.Count == index) - { - element = queue.Dequeue(); - return true; - } - } - else - { - while (e.MoveNext()) - { - if (index == 0) + if (queue.Count == indexFromEnd) { - element = e.Current; + element = queue.Dequeue(); return true; } - - index--; } } + element = default; return false; } } From 0db2ce365ff2683a267346bf249e6c094481168d Mon Sep 17 00:00:00 2001 From: Dixin Date: Tue, 16 Feb 2021 17:07:51 -0800 Subject: [PATCH 28/35] Implement dotnet#28776: LINQ APIs for index and range. Update ElementAt, keep the original behavior. --- src/libraries/System.Linq/src/System/Linq/ElementAt.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libraries/System.Linq/src/System/Linq/ElementAt.cs b/src/libraries/System.Linq/src/System/Linq/ElementAt.cs index e8e662b95c3bb3..3cfe68a6f0b4f8 100644 --- a/src/libraries/System.Linq/src/System/Linq/ElementAt.cs +++ b/src/libraries/System.Linq/src/System/Linq/ElementAt.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.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; From 1ef45694c300a2f602af4cdd596f23bb722e111a Mon Sep 17 00:00:00 2001 From: Dixin Date: Tue, 16 Feb 2021 18:21:24 -0800 Subject: [PATCH 29/35] Implement dotnet/runtime#28776: LINQ APIs for index and range. Update ElementAt, keep the original behavior. --- .../System.Linq/src/System/Linq/ElementAt.cs | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/libraries/System.Linq/src/System/Linq/ElementAt.cs b/src/libraries/System.Linq/src/System/Linq/ElementAt.cs index 3cfe68a6f0b4f8..46d9399d36230f 100644 --- a/src/libraries/System.Linq/src/System/Linq/ElementAt.cs +++ b/src/libraries/System.Linq/src/System/Linq/ElementAt.cs @@ -86,17 +86,12 @@ public static TSource ElementAt(this IEnumerable source, Index if (source is IList list) { - if (index >= 0 && index < list.Count) - { - return list[index]; - } - } - else if (TryGetElement(source, index, out TSource? element)) - { - return element; + return index >= 0 && index < list.Count ? list[index] : default; } - return 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. From 4f985120672b61bbcd99d662c9b1b9bc976cb0e1 Mon Sep 17 00:00:00 2001 From: Dixin Date: Wed, 17 Feb 2021 18:32:09 -0800 Subject: [PATCH 30/35] Implement dotnet/runtime#28776: LINQ APIs for index and range. Add unit tests for ElementAt, ElementAtOrDefault. --- .../tests/ElementAtOrDefaultTests.cs | 20 ++++++ .../System.Linq/tests/ElementAtTests.cs | 66 ++++++++++++++++++- 2 files changed, 85 insertions(+), 1 deletion(-) diff --git a/src/libraries/System.Linq/tests/ElementAtOrDefaultTests.cs b/src/libraries/System.Linq/tests/ElementAtOrDefaultTests.cs index d17c00bc5b80d2..a5355144ea1c49 100644 --- a/src/libraries/System.Linq/tests/ElementAtOrDefaultTests.cs +++ b/src/libraries/System.Linq/tests/ElementAtOrDefaultTests.cs @@ -199,6 +199,26 @@ public void NonEmptySource_Consistency_NotList() 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)); diff --git a/src/libraries/System.Linq/tests/ElementAtTests.cs b/src/libraries/System.Linq/tests/ElementAtTests.cs index e3a3df6ad49fee..fdb23b3b6e60fb 100644 --- a/src/libraries/System.Linq/tests/ElementAtTests.cs +++ b/src/libraries/System.Linq/tests/ElementAtTests.cs @@ -1,7 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Collections; using System.Collections.Generic; +using System.Collections.Immutable; using Xunit; namespace System.Linq.Tests @@ -150,6 +152,43 @@ public void MutableSourceNotList() Assert.Equal(-1, query2[2].ElementAt(^4)); } + private class ArrayWrapper : IList + { + private readonly T[] _list; + + internal ArrayWrapper(T[] list) => _list = list; + + public int Count => _list.Length; + + public T this[int index] + { + get => _list[index]; + set => _list[index] = value; + } + + public IEnumerator GetEnumerator() => ((IList)_list).GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + public void CopyTo(T[] array, int arrayIndex) => _list.CopyTo(array, arrayIndex); + + public bool Contains(T item) => _list.Contains(item); + + public void Add(T item) => throw new NotImplementedException(); + + public void Clear() => throw new NotImplementedException(); + + public bool Remove(T item) => throw new NotImplementedException(); + + public bool IsReadOnly => throw new NotImplementedException(); + + public int IndexOf(T item) => throw new NotImplementedException(); + + public void Insert(int index, T item) => throw new NotImplementedException(); + + public void RemoveAt(int index) => throw new NotImplementedException(); + } + [Fact] public void NonEmptySource_Consistency() { @@ -169,10 +208,15 @@ public void NonEmptySource_Consistency() AssertExtensions.Throws("index", () => source.ElementAt(-1)); AssertExtensions.Throws("index", () => source.ElementAt(^11)); + AssertExtensions.Throws(() => new ArrayWrapper(source).ElementAt(-1)); + AssertExtensions.Throws(() => new ArrayWrapper(source).ElementAt(^11)); AssertExtensions.Throws("index", () => source.ElementAt(10)); AssertExtensions.Throws("index", () => source.ElementAt(new Index(10))); AssertExtensions.Throws("index", () => source.ElementAt(^0)); + AssertExtensions.Throws(() => new ArrayWrapper(source).ElementAt(10)); + AssertExtensions.Throws(() => new ArrayWrapper(source).ElementAt(new Index(10))); + AssertExtensions.Throws(() => new ArrayWrapper(source).ElementAt(^0)); AssertExtensions.Throws("index", () => source.ElementAt(int.MinValue)); AssertExtensions.Throws("index", () => source.ElementAt(^int.MaxValue)); @@ -205,6 +249,26 @@ public void NonEmptySource_Consistency_NotList() AssertExtensions.Throws("index", () => ForceNotCollection(source).ElementAt(new Index(10))); AssertExtensions.Throws("index", () => ForceNotCollection(source).ElementAt(^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); + }; + + AssertExtensions.Throws("index", () => getSource().ElementAt(10)); + Assert.Equal(ElementCount + 1, moveNextCallCount); + AssertExtensions.Throws("index", () => getSource().ElementAt(new Index(10))); + Assert.Equal(ElementCount + 1, moveNextCallCount); + AssertExtensions.Throws("index", () => getSource().ElementAt(^0)); + Assert.Equal(0, moveNextCallCount); + AssertExtensions.Throws("index", () => ForceNotCollection(source).ElementAt(int.MinValue)); AssertExtensions.Throws("index", () => ForceNotCollection(source).ElementAt(^int.MaxValue)); @@ -339,7 +403,7 @@ public void NonEmptySource_Consistency_NonGenericCollection() [Fact] public void EmptySource_Consistency() { - int[] source = { }; + int[] source = { }; AssertExtensions.Throws("index", () => source.ElementAt(1)); AssertExtensions.Throws("index", () => source.ElementAt(-1)); From 872772884140a6a428bd503038e2397b5c2e262b Mon Sep 17 00:00:00 2001 From: Dixin Date: Thu, 18 Feb 2021 16:06:13 -0800 Subject: [PATCH 31/35] Implement dotnet/runtime#28776: LINQ APIs for index and range. Update unit tests. --- .../tests/ElementAtOrDefaultTests.cs | 45 +- .../System.Linq/tests/ElementAtTests.cs | 434 +++++++++--------- src/libraries/System.Linq/tests/TakeTests.cs | 50 +- 3 files changed, 293 insertions(+), 236 deletions(-) diff --git a/src/libraries/System.Linq/tests/ElementAtOrDefaultTests.cs b/src/libraries/System.Linq/tests/ElementAtOrDefaultTests.cs index a5355144ea1c49..a462be3e8cfc85 100644 --- a/src/libraries/System.Linq/tests/ElementAtOrDefaultTests.cs +++ b/src/libraries/System.Linq/tests/ElementAtOrDefaultTests.cs @@ -107,9 +107,9 @@ public void NullableArray_ValidIndex_ReturnsCorrectObject() [Fact] public void NullSource_ThrowsArgumentNullException() { - AssertExtensions.Throws("source", () => ((IEnumerable)null).ElementAtOrDefault(2)); - AssertExtensions.Throws("source", () => ((IEnumerable)null).ElementAtOrDefault(new Index(2))); - 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] @@ -144,6 +144,45 @@ public void MutableSourceNotList() 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() { diff --git a/src/libraries/System.Linq/tests/ElementAtTests.cs b/src/libraries/System.Linq/tests/ElementAtTests.cs index fdb23b3b6e60fb..b24c1d06f54c81 100644 --- a/src/libraries/System.Linq/tests/ElementAtTests.cs +++ b/src/libraries/System.Linq/tests/ElementAtTests.cs @@ -63,38 +63,38 @@ public void ElementAtRunOnce(IEnumerable source, int index, int indexFromEn [Fact] public void InvalidIndex_ThrowsArgumentOutOfRangeException() { - AssertExtensions.Throws("index", () => new int?[] { 9, 8 }.ElementAt(-1)); - AssertExtensions.Throws("index", () => new int?[] { 9, 8 }.ElementAt(^3)); - AssertExtensions.Throws("index", () => new int?[] { 9, 8 }.ElementAt(int.MaxValue)); - AssertExtensions.Throws("index", () => new int?[] { 9, 8 }.ElementAt(int.MinValue)); - AssertExtensions.Throws("index", () => new int?[] { 9, 8 }.ElementAt(new Index(int.MaxValue))); - AssertExtensions.Throws("index", () => new int?[] { 9, 8 }.ElementAt(^int.MaxValue)); - - AssertExtensions.Throws("index", () => new int[] { 1, 2, 3, 4 }.ElementAt(4)); - AssertExtensions.Throws("index", () => new int[] { 1, 2, 3, 4 }.ElementAt(new Index(4))); - AssertExtensions.Throws("index", () => new int[] { 1, 2, 3, 4 }.ElementAt(^0)); - AssertExtensions.Throws("index", () => new int[] { 1, 2, 3, 4 }.ElementAt(^5)); - - AssertExtensions.Throws("index", () => new int[0].ElementAt(0)); - AssertExtensions.Throws("index", () => new int[0].ElementAt(new Index(0))); - AssertExtensions.Throws("index", () => new int[0].ElementAt(^0)); - AssertExtensions.Throws("index", () => new int[0].ElementAt(^1)); - - AssertExtensions.Throws("index", () => NumberRangeGuaranteedNotCollectionType(-4, 5).ElementAt(-1)); - AssertExtensions.Throws("index", () => NumberRangeGuaranteedNotCollectionType(-4, 5).ElementAt(int.MinValue)); - AssertExtensions.Throws("index", () => NumberRangeGuaranteedNotCollectionType(-4, 5).ElementAt(int.MaxValue)); - AssertExtensions.Throws("index", () => NumberRangeGuaranteedNotCollectionType(-4, 5).ElementAt(^6)); - AssertExtensions.Throws("index", () => NumberRangeGuaranteedNotCollectionType(-4, 5).ElementAt(new Index(int.MaxValue))); - AssertExtensions.Throws("index", () => NumberRangeGuaranteedNotCollectionType(-4, 5).ElementAt(^int.MaxValue)); - - AssertExtensions.Throws("index", () => NumberRangeGuaranteedNotCollectionType(5, 5).ElementAt(5)); - AssertExtensions.Throws("index", () => NumberRangeGuaranteedNotCollectionType(5, 5).ElementAt(new Index(5))); - AssertExtensions.Throws("index", () => NumberRangeGuaranteedNotCollectionType(5, 5).ElementAt(^0)); - - AssertExtensions.Throws("index", () => NumberRangeGuaranteedNotCollectionType(0, 0).ElementAt(0)); - AssertExtensions.Throws("index", () => NumberRangeGuaranteedNotCollectionType(0, 0).ElementAt(new Index(0))); - AssertExtensions.Throws("index", () => NumberRangeGuaranteedNotCollectionType(0, 0).ElementAt(^0)); - AssertExtensions.Throws("index", () => NumberRangeGuaranteedNotCollectionType(0, 0).ElementAt(^1)); + 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)); + + 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] @@ -115,9 +115,9 @@ public void NullableArray_ValidIndex_ReturnsCorrectObject() [Fact] public void NullSource_ThrowsArgumentNullException() { - AssertExtensions.Throws("source", () => ((IEnumerable)null).ElementAt(2)); - AssertExtensions.Throws("source", () => ((IEnumerable)null).ElementAt(new Index(2))); - 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] @@ -152,41 +152,43 @@ public void MutableSourceNotList() Assert.Equal(-1, query2[2].ElementAt(^4)); } - private class ArrayWrapper : IList + [Fact] + public void EnumerateElements() { - private readonly T[] _list; - - internal ArrayWrapper(T[] list) => _list = list; - - public int Count => _list.Length; - - public T this[int index] + const int ElementCount = 10; + int state = -1; + int moveNextCallCount = 0; + Func> source = () => { - get => _list[index]; - set => _list[index] = value; - } - - public IEnumerator GetEnumerator() => ((IList)_list).GetEnumerator(); - - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - - public void CopyTo(T[] array, int arrayIndex) => _list.CopyTo(array, arrayIndex); - - public bool Contains(T item) => _list.Contains(item); - - public void Add(T item) => throw new NotImplementedException(); - - public void Clear() => throw new NotImplementedException(); - - public bool Remove(T item) => throw new NotImplementedException(); + state = -1; + moveNextCallCount = 0; + return new DelegateIterator( + moveNext: () => { moveNextCallCount++; return ++state < ElementCount; }, + current: () => state, + dispose: () => state = -1); + }; - public bool IsReadOnly => throw new NotImplementedException(); + Assert.Equal(0, source().ElementAt(0)); + Assert.Equal(1, moveNextCallCount); + Assert.Equal(0, source().ElementAt(new Index(0))); + Assert.Equal(1, moveNextCallCount); - public int IndexOf(T item) => throw new NotImplementedException(); + Assert.Equal(5, source().ElementAt(5)); + Assert.Equal(6, moveNextCallCount); + Assert.Equal(5, source().ElementAt(new Index(5))); + Assert.Equal(6, moveNextCallCount); - public void Insert(int index, T item) => throw new NotImplementedException(); + Assert.Equal(0, source().ElementAt(^ElementCount)); + Assert.Equal(ElementCount + 1, moveNextCallCount); + Assert.Equal(5, source().ElementAt(^5)); + Assert.Equal(ElementCount + 1, moveNextCallCount); - public void RemoveAt(int index) => throw new NotImplementedException(); + 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] @@ -206,23 +208,36 @@ public void NonEmptySource_Consistency() Assert.Equal(9, source.ElementAt(new Index(9))); Assert.Equal(9, source.ElementAt(^1)); - AssertExtensions.Throws("index", () => source.ElementAt(-1)); - AssertExtensions.Throws("index", () => source.ElementAt(^11)); - AssertExtensions.Throws(() => new ArrayWrapper(source).ElementAt(-1)); - AssertExtensions.Throws(() => new ArrayWrapper(source).ElementAt(^11)); + Assert.Throws("index", () => source.ElementAt(-1)); + Assert.Throws("index", () => source.ElementAt(^11)); - AssertExtensions.Throws("index", () => source.ElementAt(10)); - AssertExtensions.Throws("index", () => source.ElementAt(new Index(10))); - AssertExtensions.Throws("index", () => source.ElementAt(^0)); - AssertExtensions.Throws(() => new ArrayWrapper(source).ElementAt(10)); - AssertExtensions.Throws(() => new ArrayWrapper(source).ElementAt(new Index(10))); - AssertExtensions.Throws(() => new ArrayWrapper(source).ElementAt(^0)); + Assert.Throws("index", () => source.ElementAt(10)); + Assert.Throws("index", () => source.ElementAt(new Index(10))); + Assert.Throws("index", () => source.ElementAt(^0)); - AssertExtensions.Throws("index", () => source.ElementAt(int.MinValue)); - AssertExtensions.Throws("index", () => source.ElementAt(^int.MaxValue)); + Assert.Throws("index", () => source.ElementAt(int.MinValue)); + Assert.Throws("index", () => source.ElementAt(^int.MaxValue)); - AssertExtensions.Throws("index", () => source.ElementAt(int.MaxValue)); - AssertExtensions.Throws("index", () => source.ElementAt(new Index(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 indexer 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] @@ -242,38 +257,20 @@ public void NonEmptySource_Consistency_NotList() Assert.Equal(9, ForceNotCollection(source).ElementAt(new Index(9))); Assert.Equal(9, ForceNotCollection(source).ElementAt(^1)); - AssertExtensions.Throws("index", () => ForceNotCollection(source).ElementAt(-1)); - AssertExtensions.Throws("index", () => ForceNotCollection(source).ElementAt(^11)); + Assert.Throws("index", () => ForceNotCollection(source).ElementAt(-1)); + Assert.Throws("index", () => ForceNotCollection(source).ElementAt(^11)); - AssertExtensions.Throws("index", () => ForceNotCollection(source).ElementAt(10)); - AssertExtensions.Throws("index", () => ForceNotCollection(source).ElementAt(new Index(10))); - AssertExtensions.Throws("index", () => ForceNotCollection(source).ElementAt(^0)); + Assert.Throws("index", () => ForceNotCollection(source).ElementAt(10)); + Assert.Throws("index", () => ForceNotCollection(source).ElementAt(new Index(10))); + Assert.Throws("index", () => ForceNotCollection(source).ElementAt(^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); - }; - - AssertExtensions.Throws("index", () => getSource().ElementAt(10)); - Assert.Equal(ElementCount + 1, moveNextCallCount); - AssertExtensions.Throws("index", () => getSource().ElementAt(new Index(10))); - Assert.Equal(ElementCount + 1, moveNextCallCount); - AssertExtensions.Throws("index", () => getSource().ElementAt(^0)); - Assert.Equal(0, moveNextCallCount); + - AssertExtensions.Throws("index", () => ForceNotCollection(source).ElementAt(int.MinValue)); - AssertExtensions.Throws("index", () => ForceNotCollection(source).ElementAt(^int.MaxValue)); + Assert.Throws("index", () => ForceNotCollection(source).ElementAt(int.MinValue)); + Assert.Throws("index", () => ForceNotCollection(source).ElementAt(^int.MaxValue)); - AssertExtensions.Throws("index", () => ForceNotCollection(source).ElementAt(int.MaxValue)); - AssertExtensions.Throws("index", () => ForceNotCollection(source).ElementAt(new Index(int.MaxValue))); + Assert.Throws("index", () => ForceNotCollection(source).ElementAt(int.MaxValue)); + Assert.Throws("index", () => ForceNotCollection(source).ElementAt(new Index(int.MaxValue))); } [Fact] @@ -293,18 +290,18 @@ public void NonEmptySource_Consistency_ListPartition() Assert.Equal(9, ListPartitionOrEmpty(source).ElementAt(new Index(9))); Assert.Equal(9, ListPartitionOrEmpty(source).ElementAt(^1)); - AssertExtensions.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(-1)); - AssertExtensions.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(^11)); + Assert.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(-1)); + Assert.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(^11)); - AssertExtensions.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(10)); - AssertExtensions.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(new Index(10))); - AssertExtensions.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(^0)); + Assert.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(10)); + Assert.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(new Index(10))); + Assert.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(^0)); - AssertExtensions.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(int.MinValue)); - AssertExtensions.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(^int.MaxValue)); + Assert.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(int.MinValue)); + Assert.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(^int.MaxValue)); - AssertExtensions.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(int.MaxValue)); - AssertExtensions.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(new Index(int.MaxValue))); + Assert.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(int.MaxValue)); + Assert.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(new Index(int.MaxValue))); } [Fact] @@ -324,18 +321,18 @@ public void NonEmptySource_Consistency_EnumerablePartition() Assert.Equal(9, EnumerablePartitionOrEmpty(source).ElementAt(new Index(9))); Assert.Equal(9, EnumerablePartitionOrEmpty(source).ElementAt(^1)); - AssertExtensions.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(-1)); - AssertExtensions.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(^11)); + Assert.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(-1)); + Assert.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(^11)); - AssertExtensions.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(10)); - AssertExtensions.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(new Index(10))); - AssertExtensions.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(^0)); + Assert.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(10)); + Assert.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(new Index(10))); + Assert.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(^0)); - AssertExtensions.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(int.MinValue)); - AssertExtensions.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(^int.MaxValue)); + Assert.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(int.MinValue)); + Assert.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(^int.MaxValue)); - AssertExtensions.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(int.MaxValue)); - AssertExtensions.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(new Index(int.MaxValue))); + Assert.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(int.MaxValue)); + Assert.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(new Index(int.MaxValue))); } [Fact] @@ -355,18 +352,18 @@ public void NonEmptySource_Consistency_Collection() Assert.Equal(9, new TestCollection(source).ElementAt(new Index(9))); Assert.Equal(9, new TestCollection(source).ElementAt(^1)); - AssertExtensions.Throws("index", () => new TestCollection(source).ElementAt(-1)); - AssertExtensions.Throws("index", () => new TestCollection(source).ElementAt(^11)); + Assert.Throws("index", () => new TestCollection(source).ElementAt(-1)); + Assert.Throws("index", () => new TestCollection(source).ElementAt(^11)); - AssertExtensions.Throws("index", () => new TestCollection(source).ElementAt(10)); - AssertExtensions.Throws("index", () => new TestCollection(source).ElementAt(new Index(10))); - AssertExtensions.Throws("index", () => new TestCollection(source).ElementAt(^0)); + 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)); - AssertExtensions.Throws("index", () => new TestCollection(source).ElementAt(int.MinValue)); - AssertExtensions.Throws("index", () => new TestCollection(source).ElementAt(^int.MaxValue)); + Assert.Throws("index", () => new TestCollection(source).ElementAt(int.MinValue)); + Assert.Throws("index", () => new TestCollection(source).ElementAt(^int.MaxValue)); - AssertExtensions.Throws("index", () => new TestCollection(source).ElementAt(int.MaxValue)); - AssertExtensions.Throws("index", () => new TestCollection(source).ElementAt(new Index(int.MaxValue))); + Assert.Throws("index", () => new TestCollection(source).ElementAt(int.MaxValue)); + Assert.Throws("index", () => new TestCollection(source).ElementAt(new Index(int.MaxValue))); } [Fact] @@ -386,18 +383,18 @@ public void NonEmptySource_Consistency_NonGenericCollection() Assert.Equal(9, new TestNonGenericCollection(source.ToArray()).ElementAt(new Index(9))); Assert.Equal(9, new TestNonGenericCollection(source.ToArray()).ElementAt(^1)); - AssertExtensions.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(-1)); - AssertExtensions.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(^11)); + Assert.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(-1)); + Assert.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(^11)); - AssertExtensions.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(10)); - AssertExtensions.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(new Index(10))); - AssertExtensions.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(^0)); + 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)); - AssertExtensions.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(int.MinValue)); - AssertExtensions.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(^int.MaxValue)); + Assert.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(int.MinValue)); + Assert.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(^int.MaxValue)); - AssertExtensions.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(int.MaxValue)); - AssertExtensions.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(new Index(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] @@ -405,20 +402,41 @@ public void EmptySource_Consistency() { int[] source = { }; - AssertExtensions.Throws("index", () => source.ElementAt(1)); - AssertExtensions.Throws("index", () => source.ElementAt(-1)); - AssertExtensions.Throws("index", () => source.ElementAt(new Index(1))); - AssertExtensions.Throws("index", () => source.ElementAt(^1)); + 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)); - AssertExtensions.Throws("index", () => source.ElementAt(0)); - AssertExtensions.Throws("index", () => source.ElementAt(new Index(0))); - AssertExtensions.Throws("index", () => source.ElementAt(^0)); + Assert.Throws("index", () => source.ElementAt(int.MinValue)); + Assert.Throws("index", () => source.ElementAt(^int.MaxValue)); - AssertExtensions.Throws("index", () => source.ElementAt(int.MinValue)); - AssertExtensions.Throws("index", () => source.ElementAt(^int.MaxValue)); + Assert.Throws("index", () => source.ElementAt(int.MaxValue)); + Assert.Throws("index", () => source.ElementAt(new Index(int.MaxValue))); + } - AssertExtensions.Throws("index", () => source.ElementAt(int.MaxValue)); - AssertExtensions.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 indexer 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] @@ -426,20 +444,20 @@ public void EmptySource_Consistency_NotList() { int[] source = { }; - AssertExtensions.Throws("index", () => ForceNotCollection(source).ElementAt(1)); - AssertExtensions.Throws("index", () => ForceNotCollection(source).ElementAt(-1)); - AssertExtensions.Throws("index", () => ForceNotCollection(source).ElementAt(new Index(1))); - AssertExtensions.Throws("index", () => ForceNotCollection(source).ElementAt(^1)); + 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)); - AssertExtensions.Throws("index", () => ForceNotCollection(source).ElementAt(0)); - AssertExtensions.Throws("index", () => ForceNotCollection(source).ElementAt(new Index(0))); - AssertExtensions.Throws("index", () => ForceNotCollection(source).ElementAt(^0)); + Assert.Throws("index", () => ForceNotCollection(source).ElementAt(0)); + Assert.Throws("index", () => ForceNotCollection(source).ElementAt(new Index(0))); + Assert.Throws("index", () => ForceNotCollection(source).ElementAt(^0)); - AssertExtensions.Throws("index", () => ForceNotCollection(source).ElementAt(int.MinValue)); - AssertExtensions.Throws("index", () => ForceNotCollection(source).ElementAt(^int.MaxValue)); + Assert.Throws("index", () => ForceNotCollection(source).ElementAt(int.MinValue)); + Assert.Throws("index", () => ForceNotCollection(source).ElementAt(^int.MaxValue)); - AssertExtensions.Throws("index", () => ForceNotCollection(source).ElementAt(int.MaxValue)); - AssertExtensions.Throws("index", () => ForceNotCollection(source).ElementAt(new Index(int.MaxValue))); + Assert.Throws("index", () => ForceNotCollection(source).ElementAt(int.MaxValue)); + Assert.Throws("index", () => ForceNotCollection(source).ElementAt(new Index(int.MaxValue))); } [Fact] @@ -447,20 +465,20 @@ public void EmptySource_Consistency_ListPartition() { int[] source = { }; - AssertExtensions.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(1)); - AssertExtensions.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(-1)); - AssertExtensions.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(new Index(1))); - AssertExtensions.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(^1)); + 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)); - AssertExtensions.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(0)); - AssertExtensions.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(new Index(0))); - AssertExtensions.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(^0)); + Assert.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(0)); + Assert.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(new Index(0))); + Assert.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(^0)); - AssertExtensions.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(int.MinValue)); - AssertExtensions.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(^int.MaxValue)); + Assert.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(int.MinValue)); + Assert.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(^int.MaxValue)); - AssertExtensions.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(int.MaxValue)); - AssertExtensions.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(new Index(int.MaxValue))); + Assert.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(int.MaxValue)); + Assert.Throws("index", () => ListPartitionOrEmpty(source).ElementAt(new Index(int.MaxValue))); } [Fact] @@ -468,20 +486,20 @@ public void EmptySource_Consistency_EnumerablePartition() { int[] source = { }; - AssertExtensions.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(1)); - AssertExtensions.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(-1)); - AssertExtensions.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(new Index(1))); - AssertExtensions.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(^1)); + 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)); - AssertExtensions.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(0)); - AssertExtensions.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(new Index(0))); - AssertExtensions.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(^0)); + Assert.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(0)); + Assert.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(new Index(0))); + Assert.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(^0)); - AssertExtensions.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(int.MinValue)); - AssertExtensions.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(^int.MaxValue)); + Assert.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(int.MinValue)); + Assert.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(^int.MaxValue)); - AssertExtensions.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(int.MaxValue)); - AssertExtensions.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(new Index(int.MaxValue))); + Assert.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(int.MaxValue)); + Assert.Throws("index", () => EnumerablePartitionOrEmpty(source).ElementAt(new Index(int.MaxValue))); } [Fact] @@ -489,20 +507,20 @@ public void EmptySource_Consistency_Collection() { int[] source = { }; - AssertExtensions.Throws("index", () => new TestCollection(source).ElementAt(1)); - AssertExtensions.Throws("index", () => new TestCollection(source).ElementAt(-1)); - AssertExtensions.Throws("index", () => new TestCollection(source).ElementAt(new Index(1))); - AssertExtensions.Throws("index", () => new TestCollection(source).ElementAt(^1)); + 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)); - AssertExtensions.Throws("index", () => new TestCollection(source).ElementAt(0)); - AssertExtensions.Throws("index", () => new TestCollection(source).ElementAt(new Index(0))); - AssertExtensions.Throws("index", () => new TestCollection(source).ElementAt(^0)); + 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)); - AssertExtensions.Throws("index", () => new TestCollection(source).ElementAt(int.MinValue)); - AssertExtensions.Throws("index", () => new TestCollection(source).ElementAt(^int.MaxValue)); + Assert.Throws("index", () => new TestCollection(source).ElementAt(int.MinValue)); + Assert.Throws("index", () => new TestCollection(source).ElementAt(^int.MaxValue)); - AssertExtensions.Throws("index", () => new TestCollection(source).ElementAt(int.MaxValue)); - AssertExtensions.Throws("index", () => new TestCollection(source).ElementAt(new Index(int.MaxValue))); + Assert.Throws("index", () => new TestCollection(source).ElementAt(int.MaxValue)); + Assert.Throws("index", () => new TestCollection(source).ElementAt(new Index(int.MaxValue))); } [Fact] @@ -510,20 +528,20 @@ public void EmptySource_Consistency_NonGenericCollection() { int[] source = { }; - AssertExtensions.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(1)); - AssertExtensions.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(-1)); - AssertExtensions.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(new Index(1))); - AssertExtensions.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(-1)); + Assert.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(new Index(1))); + Assert.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(^1)); - AssertExtensions.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(0)); - AssertExtensions.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(new Index(0))); - AssertExtensions.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(^0)); + 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)); - AssertExtensions.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(int.MinValue)); - AssertExtensions.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(^int.MaxValue)); + Assert.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(int.MinValue)); + Assert.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(^int.MaxValue)); - AssertExtensions.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(int.MaxValue)); - AssertExtensions.Throws("index", () => new TestNonGenericCollection(source.ToArray()).ElementAt(new Index(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/TakeTests.cs b/src/libraries/System.Linq/tests/TakeTests.cs index e4222966f3d209..c4a64e6d13c223 100644 --- a/src/libraries/System.Linq/tests/TakeTests.cs +++ b/src/libraries/System.Linq/tests/TakeTests.cs @@ -256,12 +256,12 @@ public void SourceNonEmptyTakeExcessiveNotIList() public void ThrowsOnNullSource() { int[] source = null; - AssertExtensions.Throws("source", () => source.Take(5)); + Assert.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)); + 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] @@ -374,32 +374,32 @@ public void ElementAt() var taken0 = source[0].Take(3); Assert.Equal(1, taken0.ElementAt(0)); Assert.Equal(3, taken0.ElementAt(2)); - AssertExtensions.Throws("index", () => taken0.ElementAt(-1)); - AssertExtensions.Throws("index", () => taken0.ElementAt(3)); + Assert.Throws("index", () => taken0.ElementAt(-1)); + Assert.Throws("index", () => taken0.ElementAt(3)); var taken1 = source[1].Take(0..3); Assert.Equal(1, taken1.ElementAt(0)); Assert.Equal(3, taken1.ElementAt(2)); - AssertExtensions.Throws("index", () => taken1.ElementAt(-1)); - AssertExtensions.Throws("index", () => taken1.ElementAt(3)); + Assert.Throws("index", () => taken1.ElementAt(-1)); + Assert.Throws("index", () => taken1.ElementAt(3)); var taken2 = source[2].Take(^6..3); Assert.Equal(1, taken2.ElementAt(0)); Assert.Equal(3, taken2.ElementAt(2)); - AssertExtensions.Throws("index", () => taken2.ElementAt(-1)); - AssertExtensions.Throws("index", () => taken2.ElementAt(3)); + Assert.Throws("index", () => taken2.ElementAt(-1)); + Assert.Throws("index", () => taken2.ElementAt(3)); var taken3 = source[3].Take(0..^3); Assert.Equal(1, taken3.ElementAt(0)); Assert.Equal(3, taken3.ElementAt(2)); - AssertExtensions.Throws("index", () => taken3.ElementAt(-1)); - AssertExtensions.Throws("index", () => taken3.ElementAt(3)); + Assert.Throws("index", () => taken3.ElementAt(-1)); + Assert.Throws("index", () => taken3.ElementAt(3)); var taken4 = source[4].Take(^6..^3); Assert.Equal(1, taken4.ElementAt(0)); Assert.Equal(3, taken4.ElementAt(2)); - AssertExtensions.Throws("index", () => taken4.ElementAt(-1)); - AssertExtensions.Throws("index", () => taken4.ElementAt(3)); + Assert.Throws("index", () => taken4.ElementAt(-1)); + Assert.Throws("index", () => taken4.ElementAt(3)); } [Fact] @@ -409,32 +409,32 @@ public void ElementAtNotIList() var taken0 = source[0].Take(3); Assert.Equal(1, taken0.ElementAt(0)); Assert.Equal(3, taken0.ElementAt(2)); - AssertExtensions.Throws("index", () => taken0.ElementAt(-1)); - AssertExtensions.Throws("index", () => taken0.ElementAt(3)); + Assert.Throws("index", () => taken0.ElementAt(-1)); + Assert.Throws("index", () => taken0.ElementAt(3)); var taken1 = source[1].Take(0..3); Assert.Equal(1, taken1.ElementAt(0)); Assert.Equal(3, taken1.ElementAt(2)); - AssertExtensions.Throws("index", () => taken1.ElementAt(-1)); - AssertExtensions.Throws("index", () => taken1.ElementAt(3)); + Assert.Throws("index", () => taken1.ElementAt(-1)); + Assert.Throws("index", () => taken1.ElementAt(3)); var taken2 = source[2].Take(^6..3); Assert.Equal(1, taken2.ElementAt(0)); Assert.Equal(3, taken2.ElementAt(2)); - AssertExtensions.Throws("index", () => taken2.ElementAt(-1)); - AssertExtensions.Throws("index", () => taken2.ElementAt(3)); + Assert.Throws("index", () => taken2.ElementAt(-1)); + Assert.Throws("index", () => taken2.ElementAt(3)); var taken3 = source[3].Take(0..^3); Assert.Equal(1, taken3.ElementAt(0)); Assert.Equal(3, taken3.ElementAt(2)); - AssertExtensions.Throws("index", () => taken3.ElementAt(-1)); - AssertExtensions.Throws("index", () => taken3.ElementAt(3)); + Assert.Throws("index", () => taken3.ElementAt(-1)); + Assert.Throws("index", () => taken3.ElementAt(3)); var taken4 = source[4].Take(^6..^3); Assert.Equal(1, taken4.ElementAt(0)); Assert.Equal(3, taken4.ElementAt(2)); - AssertExtensions.Throws("index", () => taken4.ElementAt(-1)); - AssertExtensions.Throws("index", () => taken4.ElementAt(3)); + Assert.Throws("index", () => taken4.ElementAt(-1)); + Assert.Throws("index", () => taken4.ElementAt(3)); } [Fact] From 9a241b1432b57a01880d7ecafcb2a76d7b467560 Mon Sep 17 00:00:00 2001 From: Dixin Date: Thu, 18 Feb 2021 16:09:52 -0800 Subject: [PATCH 32/35] Implement dotnet/runtime#28776: LINQ APIs for index and range. Update unit tests. --- src/libraries/System.Linq/tests/ElementAtTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Linq/tests/ElementAtTests.cs b/src/libraries/System.Linq/tests/ElementAtTests.cs index b24c1d06f54c81..c833c045786727 100644 --- a/src/libraries/System.Linq/tests/ElementAtTests.cs +++ b/src/libraries/System.Linq/tests/ElementAtTests.cs @@ -228,7 +228,7 @@ 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 indexer throws IndexOutOfRangeException instead of ArgumentOutOfRangeException. + // 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)); @@ -424,7 +424,7 @@ public void EmptySource_Consistency_ThrowsIListIndexerException() int[] source = { }; Assert.Throws("index", () => source.ElementAt(-1)); Assert.Throws("index", () => source.ElementAt(^1)); - // ImmutableArray indexer throws IndexOutOfRangeException instead of ArgumentOutOfRangeException. + // 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)); From a6180ddc6e3c40bc6ef0896ba34e67709c441f5c Mon Sep 17 00:00:00 2001 From: Dixin Date: Thu, 18 Feb 2021 16:12:32 -0800 Subject: [PATCH 33/35] Implement dotnet/runtime#28776: LINQ APIs for index and range. Update unit tests. --- src/libraries/System.Linq/tests/ElementAtTests.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libraries/System.Linq/tests/ElementAtTests.cs b/src/libraries/System.Linq/tests/ElementAtTests.cs index c833c045786727..8644a7df0d1e9b 100644 --- a/src/libraries/System.Linq/tests/ElementAtTests.cs +++ b/src/libraries/System.Linq/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.Collections; using System.Collections.Generic; using System.Collections.Immutable; using Xunit; From 5d8279a52783c0d12c6d2d081a6d80a12bd1cf96 Mon Sep 17 00:00:00 2001 From: Dixin Date: Fri, 19 Feb 2021 14:14:07 -0800 Subject: [PATCH 34/35] Implement dotnet/runtime#28776: LINQ APIs for index and range. Update for merge. --- .../System.Linq.Queryable/src/System/Linq/CachedReflection.cs | 3 +-- .../System.Linq.Queryable/tests/TrimCompatibilityTests.cs | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) 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 de1f9e70472850..f0eb0f169bf3c0 100644 --- a/src/libraries/System.Linq.Queryable/src/System/Linq/CachedReflection.cs +++ b/src/libraries/System.Linq.Queryable/src/System/Linq/CachedReflection.cs @@ -167,8 +167,7 @@ public static MethodInfo Cast_TResult_1(Type 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; diff --git a/src/libraries/System.Linq.Queryable/tests/TrimCompatibilityTests.cs b/src/libraries/System.Linq.Queryable/tests/TrimCompatibilityTests.cs index 76d7e864ca9b48..3d02b20ae0ec13 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(); From 88d55cd7e7d1ad49b8baa993840e19dde9577222 Mon Sep 17 00:00:00 2001 From: Dixin Date: Fri, 19 Feb 2021 18:41:23 -0800 Subject: [PATCH 35/35] Implement #28776: LINQ APIs for index and range. Update unit tests. --- src/libraries/System.Linq/tests/TakeTests.cs | 1161 +++++++++--------- 1 file changed, 595 insertions(+), 566 deletions(-) diff --git a/src/libraries/System.Linq/tests/TakeTests.cs b/src/libraries/System.Linq/tests/TakeTests.cs index c4a64e6d13c223..1eea3e9c74f659 100644 --- a/src/libraries/System.Linq/tests/TakeTests.cs +++ b/src/libraries/System.Linq/tests/TakeTests.cs @@ -11,245 +11,245 @@ public class TakeTests : EnumerableTests [Fact] public void SameResultsRepeatCallsIntQuery() { - var q = Repeat(_ => from x in new[] { 9999, 0, 888, -1, 66, -777, 1, 2, -12345 } - where x > int.MinValue - select x, 5); + var q = from x in new[] { 9999, 0, 888, -1, 66, -777, 1, 2, -12345 } + where x > int.MinValue + select x; - Assert.Equal(q[0].Take(9), q[0].Take(9)); + Assert.Equal(q.Take(9), q.Take(9)); - Assert.Equal(q[1].Take(0..9), q[1].Take(0..9)); - Assert.Equal(q[2].Take(^9..9), q[2].Take(^9..9)); - Assert.Equal(q[3].Take(0..^0), q[3].Take(0..^0)); - Assert.Equal(q[4].Take(^9..^0), q[4].Take(^9..^0)); + 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] public void SameResultsRepeatCallsIntQueryIList() { - var q = Repeat(_ => (from x in new[] { 9999, 0, 888, -1, 66, -777, 1, 2, -12345 } - where x > Int32.MinValue - select x).ToList(), 5); + var q = (from x in new[] { 9999, 0, 888, -1, 66, -777, 1, 2, -12345 } + where x > Int32.MinValue + select x).ToList(); - Assert.Equal(q[0].Take(9), q[0].Take(9)); + Assert.Equal(q.Take(9), q.Take(9)); - Assert.Equal(q[1].Take(0..9), q[1].Take(0..9)); - Assert.Equal(q[2].Take(^9..9), q[2].Take(^9..9)); - Assert.Equal(q[3].Take(0..^0), q[3].Take(0..^0)); - Assert.Equal(q[4].Take(^9..^0), q[4].Take(^9..^0)); + 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] public void SameResultsRepeatCallsStringQuery() { - var q = Repeat(_ => from x in new[] { "!@#$%^", "C", "AAA", "", "Calling Twice", "SoS", string.Empty } - where !string.IsNullOrEmpty(x) - select x, 5); + var q = from x in new[] { "!@#$%^", "C", "AAA", "", "Calling Twice", "SoS", string.Empty } + where !string.IsNullOrEmpty(x) + select x; - Assert.Equal(q[0].Take(7), q[0].Take(7)); + Assert.Equal(q.Take(7), q.Take(7)); - Assert.Equal(q[1].Take(0..7), q[1].Take(0..7)); - Assert.Equal(q[2].Take(^7..7), q[2].Take(^7..7)); - Assert.Equal(q[3].Take(0..^0), q[3].Take(0..^0)); - Assert.Equal(q[4].Take(^7..^0), q[4].Take(^7..^0)); + 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 SameResultsRepeatCallsStringQueryIList() { - var q = Repeat(_ => (from x in new[] { "!@#$%^", "C", "AAA", "", "Calling Twice", "SoS", String.Empty } - where !String.IsNullOrEmpty(x) - select x).ToList(), 5); + var q = (from x in new[] { "!@#$%^", "C", "AAA", "", "Calling Twice", "SoS", String.Empty } + where !String.IsNullOrEmpty(x) + select x).ToList(); - Assert.Equal(q[0].Take(7), q[0].Take(7)); + Assert.Equal(q.Take(7), q.Take(7)); - Assert.Equal(q[1].Take(0..7), q[1].Take(0..7)); - Assert.Equal(q[2].Take(^7..7), q[2].Take(^7..7)); - Assert.Equal(q[3].Take(0..^0), q[3].Take(0..^0)); - Assert.Equal(q[4].Take(^7..^0), q[4].Take(^7..^0)); + 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() { - var source = Repeat(_ => new int[] { }, 5); - Assert.Empty(source[0].Take(5)); + var source = new int[] { }; + Assert.Empty(source.Take(5)); - Assert.Empty(source[1].Take(0..5)); - Assert.Empty(source[2].Take(^5..5)); - Assert.Empty(source[3].Take(0..^0)); - Assert.Empty(source[4].Take(^5..^0)); + 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 SourceEmptyCountPositiveNotIList() { - var source = Repeat(_ => NumberRangeGuaranteedNotCollectionType(0, 0), 5); - Assert.Empty(source[0].Take(5)); + var source = NumberRangeGuaranteedNotCollectionType(0, 0); + Assert.Empty(source.Take(5)); - Assert.Empty(source[1].Take(0..5)); - Assert.Empty(source[2].Take(^5..5)); - Assert.Empty(source[3].Take(0..^0)); - Assert.Empty(source[4].Take(^5..^0)); + 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() { - var source = Repeat(_ => new[] { 2, 5, 9, 1 }, 2); - Assert.Empty(source[0].Take(-5)); + var source = new[] { 2, 5, 9, 1 }; + Assert.Empty(source.Take(-5)); - Assert.Empty(source[1].Take(^9..0)); + Assert.Empty(source.Take(^9..0)); } [Fact] public void SourceNonEmptyCountNegativeNotIList() { - var source = Repeat(_ => ForceNotCollection(new[] { 2, 5, 9, 1 }), 2); - Assert.Empty(source[0].Take(-5)); + var source = ForceNotCollection(new[] { 2, 5, 9, 1 }); + Assert.Empty(source.Take(-5)); - Assert.Empty(source[1].Take(^9..0)); + Assert.Empty(source.Take(^9..0)); } [Fact] public void SourceNonEmptyCountZero() { - var source = Repeat(_ => new[] { 2, 5, 9, 1 }, 5); - Assert.Empty(source[0].Take(0)); + var source = new[] { 2, 5, 9, 1 }; + Assert.Empty(source.Take(0)); - Assert.Empty(source[1].Take(0..0)); - Assert.Empty(source[2].Take(^4..0)); - Assert.Empty(source[3].Take(0..^4)); - Assert.Empty(source[4].Take(^4..^4)); + 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 = Repeat(_ => ForceNotCollection(new[] { 2, 5, 9, 1 }), 5); - Assert.Empty(source[0].Take(0)); + var source = ForceNotCollection(new[] { 2, 5, 9, 1 }); + Assert.Empty(source.Take(0)); - Assert.Empty(source[1].Take(0..0)); - Assert.Empty(source[2].Take(^4..0)); - Assert.Empty(source[3].Take(0..^4)); - Assert.Empty(source[4].Take(^4..^4)); + 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() { - var source = Repeat(_ => new[] { 2, 5, 9, 1 }, 5); + var source = new[] { 2, 5, 9, 1 }; int[] expected = { 2 }; - Assert.Equal(expected, source[0].Take(1)); + Assert.Equal(expected, source.Take(1)); - Assert.Equal(expected, source[1].Take(0..1)); - Assert.Equal(expected, source[2].Take(^4..1)); - Assert.Equal(expected, source[3].Take(0..^3)); - Assert.Equal(expected, source[4].Take(^4..^3)); + 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 = Repeat(_ => ForceNotCollection(new[] { 2, 5, 9, 1 }), 5); + var source = ForceNotCollection(new[] { 2, 5, 9, 1 }); int[] expected = { 2 }; - Assert.Equal(expected, source[0].Take(1)); + Assert.Equal(expected, source.Take(1)); - Assert.Equal(expected, source[1].Take(0..1)); - Assert.Equal(expected, source[2].Take(^4..1)); - Assert.Equal(expected, source[3].Take(0..^3)); - Assert.Equal(expected, source[4].Take(^4..^3)); + 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() { - var source = Repeat(_ => new[] { 2, 5, 9, 1 }, 5); + var source = new[] { 2, 5, 9, 1 }; - Assert.Equal(source[0], source[0].Take(source.Length)); + Assert.Equal(source, source.Take(source.Length)); - Assert.Equal(source[1], source[1].Take(0..source.Length)); - Assert.Equal(source[2], source[2].Take(^source.Length..source.Length)); - Assert.Equal(source[3], source[3].Take(0..^0)); - Assert.Equal(source[4], source[4].Take(^source.Length..^0)); + 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 = Repeat(_ => ForceNotCollection(new[] { 2, 5, 9, 1 }), 5); + var source = ForceNotCollection(new[] { 2, 5, 9, 1 }); - Assert.Equal(source[0], source[0].Take(source.Count())); + Assert.Equal(source, source.Take(source.Count())); - Assert.Equal(source[1], source[1].Take(0..source[1].Count())); - Assert.Equal(source[2], source[2].Take(^source[2].Count()..source[2].Count())); - Assert.Equal(source[3], source[3].Take(0..^0)); - Assert.Equal(source[4], source[4].Take(^source[4].Count()..^0)); + 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() { - var source = Repeat(_ => new[] { 2, 5, 9, 1 }, 5); + var source = new[] { 2, 5, 9, 1 }; int[] expected = { 2, 5, 9 }; - Assert.Equal(expected, source[0].Take(3)); + Assert.Equal(expected, source.Take(3)); - Assert.Equal(expected, source[1].Take(0..3)); - Assert.Equal(expected, source[2].Take(^4..3)); - Assert.Equal(expected, source[3].Take(0..^1)); - Assert.Equal(expected, source[4].Take(^4..^1)); + 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() { - var source = Repeat(_ => new[] { 2, 5, 9, 1 }, 5); + var source = new[] { 2, 5, 9, 1 }; int[] expected = { 2, 5, 9 }; - Assert.Equal(expected, source[0].RunOnce().Take(3)); + Assert.Equal(expected, source.RunOnce().Take(3)); - Assert.Equal(expected, source[1].RunOnce().Take(0..3)); - Assert.Equal(expected, source[2].RunOnce().Take(^4..3)); - Assert.Equal(expected, source[3].RunOnce().Take(0..^1)); - Assert.Equal(expected, source[4].RunOnce().Take(^4..^1)); + 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 = Repeat(_ => ForceNotCollection(new[] { 2, 5, 9, 1 }), 5); + var source = ForceNotCollection(new[] { 2, 5, 9, 1 }); int[] expected = { 2, 5, 9 }; - Assert.Equal(expected, source[0].RunOnce().Take(3)); + Assert.Equal(expected, source.RunOnce().Take(3)); - Assert.Equal(expected, source[1].RunOnce().Take(0..3)); - Assert.Equal(expected, source[2].RunOnce().Take(^4..3)); - Assert.Equal(expected, source[3].RunOnce().Take(0..^1)); - Assert.Equal(expected, source[4].RunOnce().Take(^4..^1)); + 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() { - var source = Repeat(_ => new int?[] { 2, 5, null, 9, 1 }, 3); + var source = new int?[] { 2, 5, null, 9, 1 }; - Assert.Equal(source[0], source[0].Take(source[0].Length + 1)); + Assert.Equal(source, source.Take(source.Length + 1)); - Assert.Equal(source[1], source[1].Take(0..(source[1].Length + 1))); - Assert.Equal(source[2], source[2].Take(^(source[2].Length + 1)..(source[2].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 = Repeat(_ => ForceNotCollection(new int?[] { 2, 5, null, 9, 1 }), 3); + var source = ForceNotCollection(new int?[] { 2, 5, null, 9, 1 }); - Assert.Equal(source[0], source[0].Take(source[0].Count() + 1)); + Assert.Equal(source, source.Take(source.Count() + 1)); - Assert.Equal(source[1], source[1].Take(0..(source[1].Count() + 1))); - Assert.Equal(source[2], source[2].Take(^(source[2].Count() + 1)..(source[2].Count() + 1))); + Assert.Equal(source, source.Take(0..(source.Count() + 1))); + Assert.Equal(source, source.Take(^(source.Count() + 1)..(source.Count() + 1))); } [Fact] @@ -265,17 +265,28 @@ public void ThrowsOnNullSource() } [Fact] - public void ForcedToEnumeratorDoesntEnumerate() + public void ForcedToEnumeratorDoesNotEnumerate() { var iterator1 = NumberRangeGuaranteedNotCollectionType(0, 3).Take(2); // Don't insist on this behaviour, but check it's correct if it happens var en1 = iterator1 as IEnumerator; Assert.False(en1 != null && en1.MoveNext()); - var iterator2 = NumberRangeGuaranteedNotCollectionType(0, 3).Take(2); - // Don't insist on this behaviour, but check it's correct if it happens + 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] @@ -310,92 +321,104 @@ public void ForcedToEnumeratorDoesntEnumerateIList() var en1 = iterator1 as IEnumerator; Assert.False(en1 != null && en1.MoveNext()); - var iterator2 = NumberRangeGuaranteedNotCollectionType(0, 3).ToList().Take(2); + 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] public void FollowWithTake() { - var source = Repeat(_ => new[] { 5, 6, 7, 8 }, 5); + var source = new[] { 5, 6, 7, 8 }; var expected = new[] { 5, 6 }; - Assert.Equal(expected, source[0].Take(5).Take(3).Take(2).Take(40)); + Assert.Equal(expected, source.Take(5).Take(3).Take(2).Take(40)); - Assert.Equal(expected, source[1].Take(0..5).Take(0..3).Take(0..2).Take(0..40)); - Assert.Equal(expected, source[2].Take(^4..5).Take(^4..3).Take(^3..2).Take(^2..40)); - Assert.Equal(expected, source[3].Take(0..^0).Take(0..^1).Take(0..^1).Take(0..^0)); - Assert.Equal(expected, source[4].Take(^4..^0).Take(^4..^1).Take(^3..^1).Take(^2..^0)); + 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] public void FollowWithTakeNotIList() { - var source = Repeat(_ => NumberRangeGuaranteedNotCollectionType(5, 4), 5); + var source = NumberRangeGuaranteedNotCollectionType(5, 4); var expected = new[] { 5, 6 }; - Assert.Equal(expected, source[0].Take(5).Take(3).Take(2)); + Assert.Equal(expected, source.Take(5).Take(3).Take(2)); - Assert.Equal(expected, source[1].Take(0..5).Take(0..3).Take(0..2)); - Assert.Equal(expected, source[2].Take(^4..5).Take(^4..3).Take(^3..2)); - Assert.Equal(expected, source[3].Take(0..^0).Take(0..^1).Take(0..^1)); - Assert.Equal(expected, source[4].Take(^4..^0).Take(^4..^1).Take(^3..^1)); + 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] public void FollowWithSkip() { - var source = Repeat(_ => new[] { 1, 2, 3, 4, 5, 6 }, 5); + var source = new[] { 1, 2, 3, 4, 5, 6 }; var expected = new[] { 3, 4, 5 }; - Assert.Equal(expected, source[0].Take(5).Skip(2).Skip(-4)); + Assert.Equal(expected, source.Take(5).Skip(2).Skip(-4)); - Assert.Equal(expected, source[1].Take(0..5).Skip(2).Skip(-4)); - Assert.Equal(expected, source[2].Take(^6..5).Skip(2).Skip(-4)); - Assert.Equal(expected, source[3].Take(0..^1).Skip(2).Skip(-4)); - Assert.Equal(expected, source[4].Take(^6..^1).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 FollowWithSkipNotIList() { - var source = Repeat(_ => NumberRangeGuaranteedNotCollectionType(1, 6), 5); + var source = NumberRangeGuaranteedNotCollectionType(1, 6); var expected = new[] { 3, 4, 5 }; - Assert.Equal(expected, source[0].Take(5).Skip(2).Skip(-4)); + Assert.Equal(expected, source.Take(5).Skip(2).Skip(-4)); - Assert.Equal(expected, source[1].Take(0..5).Skip(2).Skip(-4)); - Assert.Equal(expected, source[2].Take(^6..5).Skip(2).Skip(-4)); - Assert.Equal(expected, source[3].Take(0..^1).Skip(2).Skip(-4)); - Assert.Equal(expected, source[4].Take(^6..^1).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 = Repeat(_ => new[] { 1, 2, 3, 4, 5, 6 }, 5); - var taken0 = source[0].Take(3); + var source = 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[1].Take(0..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[2].Take(^6..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[3].Take(0..^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[4].Take(^6..^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)); @@ -405,32 +428,32 @@ public void ElementAt() [Fact] public void ElementAtNotIList() { - var source = Repeat(_ => ForceNotCollection(new[] { 1, 2, 3, 4, 5, 6 }), 5); - var taken0 = source[0].Take(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[1].Take(0..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[2].Take(^6..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[3].Take(0..^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[4].Take(^6..^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)); @@ -440,32 +463,32 @@ public void ElementAtNotIList() [Fact] public void ElementAtOrDefault() { - var source = Repeat(_ => new[] { 1, 2, 3, 4, 5, 6 }, 5); - var taken0 = source[0].Take(3); + var source = 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[1].Take(0..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[2].Take(^6..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[3].Take(0..^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[4].Take(^6..^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)); @@ -475,32 +498,32 @@ public void ElementAtOrDefault() [Fact] public void ElementAtOrDefaultNotIList() { - var source = Repeat(_ => ForceNotCollection(new[] { 1, 2, 3, 4, 5, 6 }), 5); - var taken0 = source[0].Take(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[1].Take(0..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[2].Take(^6..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[3].Take(0..^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[4].Take(^6..^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)); @@ -510,515 +533,515 @@ public void ElementAtOrDefaultNotIList() [Fact] public void First() { - var source = Repeat(_ => new[] { 1, 2, 3, 4, 5 }, 5); - Assert.Equal(1, source[0].Take(1).First()); - Assert.Equal(1, source[0].Take(4).First()); - Assert.Equal(1, source[0].Take(40).First()); - Assert.Throws(() => source[0].Take(0).First()); - Assert.Throws(() => source[0].Skip(5).Take(10).First()); - - Assert.Equal(1, source[1].Take(0..1).First()); - Assert.Equal(1, source[1].Take(0..4).First()); - Assert.Equal(1, source[1].Take(0..40).First()); - Assert.Throws(() => source[1].Take(0..0).First()); - Assert.Throws(() => source[1].Skip(5).Take(0..10).First()); - - Assert.Equal(1, source[2].Take(^5..1).First()); - Assert.Equal(1, source[2].Take(^5..4).First()); - Assert.Equal(1, source[2].Take(^5..40).First()); - Assert.Throws(() => source[2].Take(^5..0).First()); - Assert.Throws(() => source[2].Skip(5).Take(^5..10).First()); - - Assert.Equal(1, source[3].Take(0..^4).First()); - Assert.Equal(1, source[3].Take(0..^1).First()); - Assert.Equal(1, source[3].Take(0..^0).First()); - Assert.Throws(() => source[3].Take(0..^5).First()); - Assert.Throws(() => source[3].Skip(5).Take(0..^5).First()); - - Assert.Equal(1, source[4].Take(^5..^4).First()); - Assert.Equal(1, source[4].Take(^5..^1).First()); - Assert.Equal(1, source[4].Take(^5..^0).First()); - Assert.Throws(() => source[4].Take(^5..^5).First()); - Assert.Throws(() => source[4].Skip(5).Take(^10..^0).First()); + var source = 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] public void FirstNotIList() { - var source = Repeat(_ => ForceNotCollection(new[] { 1, 2, 3, 4, 5 }), 5); - Assert.Equal(1, source[0].Take(1).First()); - Assert.Equal(1, source[0].Take(4).First()); - Assert.Equal(1, source[0].Take(40).First()); - Assert.Throws(() => source[0].Take(0).First()); - Assert.Throws(() => source[0].Skip(5).Take(10).First()); + 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[1].Take(0..1).First()); - Assert.Equal(1, source[1].Take(0..4).First()); - Assert.Equal(1, source[1].Take(0..40).First()); - Assert.Throws(() => source[1].Take(0..0).First()); - Assert.Throws(() => source[1].Skip(5).Take(0..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[2].Take(^5..1).First()); - Assert.Equal(1, source[2].Take(^5..4).First()); - Assert.Equal(1, source[2].Take(^5..40).First()); - Assert.Throws(() => source[2].Take(^5..0).First()); - Assert.Throws(() => source[2].Skip(5).Take(^5..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[3].Take(0..^4).First()); - Assert.Equal(1, source[3].Take(0..^1).First()); - Assert.Equal(1, source[3].Take(0..^0).First()); - Assert.Throws(() => source[3].Take(0..^5).First()); - Assert.Throws(() => source[3].Skip(5).Take(0..^5).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[4].Take(^5..^4).First()); - Assert.Equal(1, source[4].Take(^5..^1).First()); - Assert.Equal(1, source[4].Take(^5..^0).First()); - Assert.Throws(() => source[4].Take(^5..^5).First()); - Assert.Throws(() => source[4].Skip(5).Take(^10..^0).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 FirstOrDefault() { - var source = Repeat(_ => new[] { 1, 2, 3, 4, 5 }, 5); - Assert.Equal(1, source[0].Take(1).FirstOrDefault()); - Assert.Equal(1, source[0].Take(4).FirstOrDefault()); - Assert.Equal(1, source[0].Take(40).FirstOrDefault()); - Assert.Equal(0, source[0].Take(0).FirstOrDefault()); - Assert.Equal(0, source[0].Skip(5).Take(10).FirstOrDefault()); - - Assert.Equal(1, source[1].Take(0..1).FirstOrDefault()); - Assert.Equal(1, source[1].Take(0..4).FirstOrDefault()); - Assert.Equal(1, source[1].Take(0..40).FirstOrDefault()); - Assert.Equal(0, source[1].Take(0..0).FirstOrDefault()); - Assert.Equal(0, source[1].Skip(5).Take(0..10).FirstOrDefault()); - - Assert.Equal(1, source[2].Take(^5..1).FirstOrDefault()); - Assert.Equal(1, source[2].Take(^5..4).FirstOrDefault()); - Assert.Equal(1, source[2].Take(^5..40).FirstOrDefault()); - Assert.Equal(0, source[2].Take(^5..0).FirstOrDefault()); - Assert.Equal(0, source[2].Skip(5).Take(^10..10).FirstOrDefault()); - - Assert.Equal(1, source[3].Take(0..^4).FirstOrDefault()); - Assert.Equal(1, source[3].Take(0..^1).FirstOrDefault()); - Assert.Equal(1, source[3].Take(0..^0).FirstOrDefault()); - Assert.Equal(0, source[3].Take(0..^5).FirstOrDefault()); - Assert.Equal(0, source[3].Skip(5).Take(0..^10).FirstOrDefault()); - - Assert.Equal(1, source[4].Take(^5..^4).FirstOrDefault()); - Assert.Equal(1, source[4].Take(^5..^1).FirstOrDefault()); - Assert.Equal(1, source[4].Take(^5..^0).FirstOrDefault()); - Assert.Equal(0, source[4].Take(^5..^5).FirstOrDefault()); - Assert.Equal(0, source[4].Skip(5).Take(^10..^0).FirstOrDefault()); + var source = 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] public void FirstOrDefaultNotIList() { - var source = Repeat(_ => ForceNotCollection(new[] { 1, 2, 3, 4, 5 }), 5); - Assert.Equal(1, source[0].Take(1).FirstOrDefault()); - Assert.Equal(1, source[0].Take(4).FirstOrDefault()); - Assert.Equal(1, source[0].Take(40).FirstOrDefault()); - Assert.Equal(0, source[0].Take(0).FirstOrDefault()); - Assert.Equal(0, source[0].Skip(5).Take(10).FirstOrDefault()); + 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[1].Take(0..1).FirstOrDefault()); - Assert.Equal(1, source[1].Take(0..4).FirstOrDefault()); - Assert.Equal(1, source[1].Take(0..40).FirstOrDefault()); - Assert.Equal(0, source[1].Take(0..0).FirstOrDefault()); - Assert.Equal(0, source[1].Skip(5).Take(0..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[2].Take(^5..1).FirstOrDefault()); - Assert.Equal(1, source[2].Take(^5..4).FirstOrDefault()); - Assert.Equal(1, source[2].Take(^5..40).FirstOrDefault()); - Assert.Equal(0, source[2].Take(^5..0).FirstOrDefault()); - Assert.Equal(0, source[2].Skip(5).Take(^10..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[3].Take(0..^4).FirstOrDefault()); - Assert.Equal(1, source[3].Take(0..^1).FirstOrDefault()); - Assert.Equal(1, source[3].Take(0..^0).FirstOrDefault()); - Assert.Equal(0, source[3].Take(0..^5).FirstOrDefault()); - Assert.Equal(0, source[3].Skip(5).Take(0..^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[4].Take(^5..^4).FirstOrDefault()); - Assert.Equal(1, source[4].Take(^5..^1).FirstOrDefault()); - Assert.Equal(1, source[4].Take(^5..^0).FirstOrDefault()); - Assert.Equal(0, source[4].Take(^5..^5).FirstOrDefault()); - Assert.Equal(0, source[4].Skip(5).Take(^10..^0).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 Last() { - var source = Repeat(_ => new[] { 1, 2, 3, 4, 5 }, 5); - Assert.Equal(1, source[0].Take(1).Last()); - Assert.Equal(5, source[0].Take(5).Last()); - Assert.Equal(5, source[0].Take(40).Last()); - Assert.Throws(() => source[0].Take(0).Last()); + var source = 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(() => Array.Empty().Take(40).Last()); - Assert.Equal(1, source[1].Take(0..1).Last()); - Assert.Equal(5, source[1].Take(0..5).Last()); - Assert.Equal(5, source[1].Take(0..40).Last()); - Assert.Throws(() => source[1].Take(0..0).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[2].Take(^5..1).Last()); - Assert.Equal(5, source[2].Take(^5..5).Last()); - Assert.Equal(5, source[2].Take(^5..40).Last()); - Assert.Throws(() => source[2].Take(^5..0).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[3].Take(0..^4).Last()); - Assert.Equal(5, source[3].Take(0..^0).Last()); - Assert.Equal(5, source[3].Take(3..^0).Last()); - Assert.Throws(() => source[3].Take(0..^5).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[4].Take(^5..^4).Last()); - Assert.Equal(5, source[4].Take(^5..^0).Last()); - Assert.Equal(5, source[4].Take(^5..^0).Last()); - Assert.Throws(() => source[4].Take(^5..^5).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 = Repeat(_ => ForceNotCollection(new[] { 1, 2, 3, 4, 5 }), 5); - Assert.Equal(1, source[0].Take(1).Last()); - Assert.Equal(5, source[0].Take(5).Last()); - Assert.Equal(5, source[0].Take(40).Last()); - Assert.Throws(() => source[0].Take(0).Last()); + 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(() => ForceNotCollection(Array.Empty()).Take(40).Last()); - Assert.Equal(1, source[1].Take(0..1).Last()); - Assert.Equal(5, source[1].Take(0..5).Last()); - Assert.Equal(5, source[1].Take(0..40).Last()); - Assert.Throws(() => source[1].Take(0..0).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[2].Take(^5..1).Last()); - Assert.Equal(5, source[2].Take(^5..5).Last()); - Assert.Equal(5, source[2].Take(^5..40).Last()); - Assert.Throws(() => source[2].Take(^5..0).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[3].Take(0..^4).Last()); - Assert.Equal(5, source[3].Take(0..^0).Last()); - Assert.Equal(5, source[3].Take(3..^0).Last()); - Assert.Throws(() => source[3].Take(0..^5).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[4].Take(^5..^4).Last()); - Assert.Equal(5, source[4].Take(^5..^0).Last()); - Assert.Equal(5, source[4].Take(^5..^0).Last()); - Assert.Throws(() => source[4].Take(^5..^5).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] public void LastOrDefault() { - var source = Repeat(_ => new[] { 1, 2, 3, 4, 5 }, 5); - Assert.Equal(1, source[0].Take(1).LastOrDefault()); - Assert.Equal(5, source[0].Take(5).LastOrDefault()); - Assert.Equal(5, source[0].Take(40).LastOrDefault()); - Assert.Equal(0, source[0].Take(0).LastOrDefault()); + var source = 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, Array.Empty().Take(40).LastOrDefault()); - Assert.Equal(1, source[1].Take(0..1).LastOrDefault()); - Assert.Equal(5, source[1].Take(0..5).LastOrDefault()); - Assert.Equal(5, source[1].Take(0..40).LastOrDefault()); - Assert.Equal(0, source[1].Take(0..0).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[2].Take(^5..1).LastOrDefault()); - Assert.Equal(5, source[2].Take(^5..5).LastOrDefault()); - Assert.Equal(5, source[2].Take(^5..40).LastOrDefault()); - Assert.Equal(0, source[2].Take(^5..0).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[3].Take(0..^4).LastOrDefault()); - Assert.Equal(5, source[3].Take(0..^0).LastOrDefault()); - Assert.Equal(5, source[3].Take(3..^0).LastOrDefault()); - Assert.Equal(0, source[3].Take(0..^5).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[4].Take(^5..^4).LastOrDefault()); - Assert.Equal(5, source[4].Take(^5..^0).LastOrDefault()); - Assert.Equal(5, source[4].Take(^40..^0).LastOrDefault()); - Assert.Equal(0, source[4].Take(^5..^5).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 = Repeat(_ => ForceNotCollection(new[] { 1, 2, 3, 4, 5 }), 5); - Assert.Equal(1, source[0].Take(1).LastOrDefault()); - Assert.Equal(5, source[0].Take(5).LastOrDefault()); - Assert.Equal(5, source[0].Take(40).LastOrDefault()); - Assert.Equal(0, source[0].Take(0).LastOrDefault()); + 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, ForceNotCollection(Array.Empty()).Take(40).LastOrDefault()); - Assert.Equal(1, source[1].Take(0..1).LastOrDefault()); - Assert.Equal(5, source[1].Take(0..5).LastOrDefault()); - Assert.Equal(5, source[1].Take(0..40).LastOrDefault()); - Assert.Equal(0, source[1].Take(0..0).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[2].Take(^5..1).LastOrDefault()); - Assert.Equal(5, source[2].Take(^5..5).LastOrDefault()); - Assert.Equal(5, source[2].Take(^5..40).LastOrDefault()); - Assert.Equal(0, source[2].Take(^5..0).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[3].Take(0..^4).LastOrDefault()); - Assert.Equal(5, source[3].Take(0..^0).LastOrDefault()); - Assert.Equal(5, source[3].Take(3..^0).LastOrDefault()); - Assert.Equal(0, source[3].Take(0..^5).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[4].Take(^5..^4).LastOrDefault()); - Assert.Equal(5, source[4].Take(^5..^0).LastOrDefault()); - Assert.Equal(5, source[4].Take(^40..^0).LastOrDefault()); - Assert.Equal(0, source[4].Take(^5..^5).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] public void ToArray() { - var source = Repeat(_ => new[] { 1, 2, 3, 4, 5 }, 5); - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[0].Take(5).ToArray()); - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[0].Take(6).ToArray()); - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[0].Take(40).ToArray()); - Assert.Equal(new[] { 1, 2, 3, 4 }, source[0].Take(4).ToArray()); - Assert.Equal(1, source[0].Take(1).ToArray().Single()); - Assert.Empty(source[0].Take(0).ToArray()); - Assert.Empty(source[0].Take(-10).ToArray()); - - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[1].Take(0..5).ToArray()); - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[1].Take(0..6).ToArray()); - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[1].Take(0..40).ToArray()); - Assert.Equal(new[] { 1, 2, 3, 4 }, source[1].Take(0..4).ToArray()); - Assert.Equal(1, source[1].Take(0..1).ToArray().Single()); - Assert.Empty(source[1].Take(0..0).ToArray()); - - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[2].Take(^5..5).ToArray()); - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[2].Take(^5..6).ToArray()); - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[2].Take(^5..40).ToArray()); - Assert.Equal(new[] { 1, 2, 3, 4 }, source[2].Take(^5..4).ToArray()); - Assert.Equal(1, source[2].Take(^5..1).ToArray().Single()); - Assert.Empty(source[2].Take(^5..0).ToArray()); - Assert.Empty(source[2].Take(^15..0).ToArray()); - - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[3].Take(0..^0).ToArray()); - Assert.Equal(new[] { 1, 2, 3, 4 }, source[3].Take(0..^1).ToArray()); - Assert.Equal(1, source[3].Take(0..^4).ToArray().Single()); - Assert.Empty(source[3].Take(0..^5).ToArray()); - Assert.Empty(source[3].Take(0..^15).ToArray()); - - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[4].Take(^5..^0).ToArray()); - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[4].Take(^6..^0).ToArray()); - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[4].Take(^45..^0).ToArray()); - Assert.Equal(new[] { 1, 2, 3, 4 }, source[4].Take(^5..^1).ToArray()); - Assert.Equal(1, source[4].Take(^5..^4).ToArray().Single()); - Assert.Empty(source[4].Take(^5..^5).ToArray()); - Assert.Empty(source[4].Take(^15..^5).ToArray()); + var source = 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()); + Assert.Equal(new[] { 1, 2, 3, 4 }, source.Take(4).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 = Repeat(_ => ForceNotCollection(new[] { 1, 2, 3, 4, 5 }), 5); - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[0].Take(5).ToArray()); - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[0].Take(6).ToArray()); - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[0].Take(40).ToArray()); - Assert.Equal(new[] { 1, 2, 3, 4 }, source[0].Take(4).ToArray()); - Assert.Equal(1, source[0].Take(1).ToArray().Single()); - Assert.Empty(source[0].Take(0).ToArray()); - Assert.Empty(source[0].Take(-10).ToArray()); - - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[1].Take(0..5).ToArray()); - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[1].Take(0..6).ToArray()); - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[1].Take(0..40).ToArray()); - Assert.Equal(new[] { 1, 2, 3, 4 }, source[1].Take(0..4).ToArray()); - Assert.Equal(1, source[1].Take(0..1).ToArray().Single()); - Assert.Empty(source[1].Take(0..0).ToArray()); - - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[2].Take(^5..5).ToArray()); - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[2].Take(^5..6).ToArray()); - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[2].Take(^5..40).ToArray()); - Assert.Equal(new[] { 1, 2, 3, 4 }, source[2].Take(^5..4).ToArray()); - Assert.Equal(1, source[2].Take(^5..1).ToArray().Single()); - Assert.Empty(source[2].Take(^5..0).ToArray()); - Assert.Empty(source[2].Take(^15..0).ToArray()); - - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[3].Take(0..^0).ToArray()); - Assert.Equal(new[] { 1, 2, 3, 4 }, source[3].Take(0..^1).ToArray()); - Assert.Equal(1, source[3].Take(0..^4).ToArray().Single()); - Assert.Empty(source[3].Take(0..^5).ToArray()); - Assert.Empty(source[3].Take(0..^15).ToArray()); - - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[4].Take(^5..^0).ToArray()); - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[4].Take(^6..^0).ToArray()); - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[4].Take(^45..^0).ToArray()); - Assert.Equal(new[] { 1, 2, 3, 4 }, source[4].Take(^5..^1).ToArray()); - Assert.Equal(1, source[4].Take(^5..^4).ToArray().Single()); - Assert.Empty(source[4].Take(^5..^5).ToArray()); - Assert.Empty(source[4].Take(^15..^5).ToArray()); + 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()); + Assert.Equal(new[] { 1, 2, 3, 4 }, source.Take(4).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 ToList() { - var source = Repeat(_ => new[] { 1, 2, 3, 4, 5 }, 5); - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[0].Take(5).ToList()); - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[0].Take(6).ToList()); - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[0].Take(40).ToList()); - Assert.Equal(new[] { 1, 2, 3, 4 }, source[0].Take(4).ToList()); - Assert.Equal(1, source[0].Take(1).ToList().Single()); - Assert.Empty(source[0].Take(0).ToList()); - Assert.Empty(source[0].Take(-10).ToList()); - - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[1].Take(0..5).ToList()); - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[1].Take(0..6).ToList()); - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[1].Take(0..40).ToList()); - Assert.Equal(new[] { 1, 2, 3, 4 }, source[1].Take(0..4).ToList()); - Assert.Equal(1, source[1].Take(0..1).ToList().Single()); - Assert.Empty(source[1].Take(0..0).ToList()); - - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[2].Take(^5..5).ToList()); - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[2].Take(^5..6).ToList()); - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[2].Take(^5..40).ToList()); - Assert.Equal(new[] { 1, 2, 3, 4 }, source[2].Take(^5..4).ToList()); - Assert.Equal(1, source[2].Take(^5..1).ToList().Single()); - Assert.Empty(source[2].Take(^5..0).ToList()); - Assert.Empty(source[2].Take(^15..0).ToList()); - - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[3].Take(0..^0).ToList()); - Assert.Equal(new[] { 1, 2, 3, 4 }, source[3].Take(0..^1).ToList()); - Assert.Equal(1, source[3].Take(0..^4).ToList().Single()); - Assert.Empty(source[3].Take(0..^5).ToList()); - Assert.Empty(source[3].Take(0..^15).ToList()); - - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[4].Take(^5..^0).ToList()); - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[4].Take(^6..^0).ToList()); - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[4].Take(^45..^0).ToList()); - Assert.Equal(new[] { 1, 2, 3, 4 }, source[4].Take(^5..^1).ToList()); - Assert.Equal(1, source[4].Take(^5..^4).ToList().Single()); - Assert.Empty(source[4].Take(^5..^5).ToList()); - Assert.Empty(source[4].Take(^15..^5).ToList()); + var source = 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()); + Assert.Equal(new[] { 1, 2, 3, 4 }, source.Take(4).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 = Repeat(_ => ForceNotCollection(new[] { 1, 2, 3, 4, 5 }), 5); - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[0].Take(5).ToList()); - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[0].Take(6).ToList()); - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[0].Take(40).ToList()); - Assert.Equal(new[] { 1, 2, 3, 4 }, source[0].Take(4).ToList()); - Assert.Equal(1, source[0].Take(1).ToList().Single()); - Assert.Empty(source[0].Take(0).ToList()); - Assert.Empty(source[0].Take(-10).ToList()); - - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[1].Take(0..5).ToList()); - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[1].Take(0..6).ToList()); - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[1].Take(0..40).ToList()); - Assert.Equal(new[] { 1, 2, 3, 4 }, source[1].Take(0..4).ToList()); - Assert.Equal(1, source[1].Take(0..1).ToList().Single()); - Assert.Empty(source[1].Take(0..0).ToList()); - - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[2].Take(^5..5).ToList()); - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[2].Take(^5..6).ToList()); - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[2].Take(^5..40).ToList()); - Assert.Equal(new[] { 1, 2, 3, 4 }, source[2].Take(^5..4).ToList()); - Assert.Equal(1, source[2].Take(^5..1).ToList().Single()); - Assert.Empty(source[2].Take(^5..0).ToList()); - Assert.Empty(source[2].Take(^15..0).ToList()); - - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[3].Take(0..^0).ToList()); - Assert.Equal(new[] { 1, 2, 3, 4 }, source[3].Take(0..^1).ToList()); - Assert.Equal(1, source[3].Take(0..^4).ToList().Single()); - Assert.Empty(source[3].Take(0..^5).ToList()); - Assert.Empty(source[3].Take(0..^15).ToList()); - - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[4].Take(^5..^0).ToList()); - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[4].Take(^6..^0).ToList()); - Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source[4].Take(^45..^0).ToList()); - Assert.Equal(new[] { 1, 2, 3, 4 }, source[4].Take(^5..^1).ToList()); - Assert.Equal(1, source[4].Take(^5..^4).ToList().Single()); - Assert.Empty(source[4].Take(^5..^5).ToList()); - Assert.Empty(source[4].Take(^15..^5).ToList()); + 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()); + Assert.Equal(new[] { 1, 2, 3, 4 }, source.Take(4).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 TakeCanOnlyBeOneList() { - var source = Repeat(_ => new[] { 2, 4, 6, 8, 10 }, 5); - Assert.Equal(new[] { 2 }, source[0].Take(1)); - Assert.Equal(new[] { 4 }, source[0].Skip(1).Take(1)); - Assert.Equal(new[] { 6 }, source[0].Take(3).Skip(2)); - Assert.Equal(new[] { 2 }, source[0].Take(3).Take(1)); + var source = 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[1].Take(0..1)); - Assert.Equal(new[] { 4 }, source[1].Skip(1).Take(0..1)); - Assert.Equal(new[] { 6 }, source[1].Take(0..3).Skip(2)); - Assert.Equal(new[] { 2 }, source[1].Take(0..3).Take(0..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[2].Take(^5..1)); - Assert.Equal(new[] { 4 }, source[2].Skip(1).Take(^4..1)); - Assert.Equal(new[] { 6 }, source[2].Take(^5..3).Skip(2)); - Assert.Equal(new[] { 2 }, source[2].Take(^5..3).Take(^4..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[3].Take(0..^4)); - Assert.Equal(new[] { 4 }, source[3].Skip(1).Take(0..^3)); - Assert.Equal(new[] { 6 }, source[3].Take(0..^2).Skip(2)); - Assert.Equal(new[] { 2 }, source[3].Take(0..^2).Take(0..^2)); + 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[4].Take(^5..^4)); - Assert.Equal(new[] { 4 }, source[4].Skip(1).Take(^4..^3)); - Assert.Equal(new[] { 6 }, source[4].Take(^5..^2).Skip(2)); - Assert.Equal(new[] { 2 }, source[4].Take(^5..^2).Take(^4..^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 = Repeat(_ => ForceNotCollection(new[] { 2, 4, 6, 8, 10 }), 5); - Assert.Equal(new[] { 2 }, source[0].Take(1)); - Assert.Equal(new[] { 4 }, source[0].Skip(1).Take(1)); - Assert.Equal(new[] { 6 }, source[0].Take(3).Skip(2)); - Assert.Equal(new[] { 2 }, source[0].Take(3).Take(1)); + 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[0].Take(0..1)); - Assert.Equal(new[] { 4 }, source[0].Skip(1).Take(0..1)); - Assert.Equal(new[] { 6 }, source[0].Take(0..3).Skip(2)); - Assert.Equal(new[] { 2 }, source[0].Take(0..3).Take(0..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[2].Take(^5..1)); - Assert.Equal(new[] { 4 }, source[2].Skip(1).Take(^4..1)); - Assert.Equal(new[] { 6 }, source[2].Take(^5..3).Skip(2)); - Assert.Equal(new[] { 2 }, source[2].Take(^5..3).Take(^4..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[3].Take(0..^4)); - Assert.Equal(new[] { 4 }, source[3].Skip(1).Take(0..^3)); - Assert.Equal(new[] { 6 }, source[3].Take(0..^2).Skip(2)); - Assert.Equal(new[] { 2 }, source[3].Take(0..^2).Take(0..^2)); + 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[4].Take(^5..^4)); - Assert.Equal(new[] { 4 }, source[4].Skip(1).Take(^4..^3)); - Assert.Equal(new[] { 6 }, source[4].Take(^5..^2).Skip(2)); - Assert.Equal(new[] { 2 }, source[4].Take(^5..^2).Take(^4..^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 = Repeat(_ => new[] { 1, 2, 3, 4, 5 }, 5); + var source = new[] { 1, 2, 3, 4, 5 }; var taken1 = source.Take(3); Assert.Equal(taken1, taken1); @@ -1038,7 +1061,7 @@ public void RepeatEnumerating() [Fact] public void RepeatEnumeratingNotList() { - var source = Repeat(_ => ForceNotCollection(new[] { 1, 2, 3, 4, 5 }), 5); + var source = ForceNotCollection(new[] { 1, 2, 3, 4, 5 }); var taken1 = source.Take(3); Assert.Equal(taken1, taken1); @@ -1271,12 +1294,18 @@ public void ElementAtOfLazySkipTakeChain(int[] source, int skip, int take, int[] [InlineData(2, 3)] public void DisposeSource(int sourceCount, int count) { - int[] state = new int[5]; + bool[] isIteratorDisposed = new bool[5]; - var source = Repeat(index => new DelegateIterator( - moveNext: () => ++state[index] <= sourceCount, - current: () => 0, - dispose: () => state[index] = -1), 5); + var source = Repeat( + index => + { + int state = 0; + return new DelegateIterator( + moveNext: () => ++state <= sourceCount, + current: () => 0, + dispose: () => { state = -1; isIteratorDisposed[index] = true; }); + }, + 5); IEnumerator iterator0 = source[0].Take(count).GetEnumerator(); int iteratorCount0 = Math.Min(sourceCount, Math.Max(0, count)); @@ -1287,16 +1316,16 @@ public void DisposeSource(int sourceCount, int count) // 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 expected0 = count <= 0 ? 0 : -1; - Assert.Equal(expected0, state[0]); + 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. - int expected1 = end == 0 ? 0 : -1; - Assert.Equal(expected1, state[1]); + bool isItertorNotEmpty1 = end != 0; + Assert.Equal(isItertorNotEmpty1, isIteratorDisposed[1]); int startIndexFromEnd = Math.Max(sourceCount, end); int endIndexFromEnd = Math.Max(0, sourceCount - end); @@ -1305,21 +1334,21 @@ public void DisposeSource(int sourceCount, int count) 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. - int expected2 = startIndexFromEnd == 0 ? 0 : -1; - Assert.Equal(expected2, state[2]); + 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.Equal(-1, state[3]); + 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. - int expected4 = startIndexFromEnd == 0 || startIndexFromEnd <= endIndexFromEnd ? 0 : -1; - Assert.Equal(expected4, state[4]); + bool isItertorNotEmpty4 = startIndexFromEnd != 0 && startIndexFromEnd > endIndexFromEnd; + Assert.Equal(isItertorNotEmpty4, isIteratorDisposed[4]); } [Fact]