My PR #48559 "Add LINQ APIs for Index and Range" was just merged, and this is a following up. @eiriktsarpalis @stephentoub
Background:
- LINQ internally use
IPartition<T> to optimize the implementation of partitioning operators, like Take, Skip, ElementAt
- Later, more partitioning operators are added for LINQ, like
TakeLast, SkipLast, Take(System.Range), ElementAt(System.Index). These new APIs are implemented by yield return.
Proposal
It is best to have an unified implementation of all the partitioning and element operators based on IPartition<T>.
Internal API changes
Current IPartition<T>:
interface IPartition<TSource>
{
TSource? TryGetElementAt(int index, out bool found);
IPartition<TSource> Take(int count);
IPartition<TSource> Skip(int count);
// Other members ...
}
- Update
IPartition<T> to support indexes from start or end:
interface IPartition<TSource>
{
// New members.
bool TryGetElementAt(int index, bool isIndexFromEnd, [MaybeNullWhen(false)] out TSource element);
IPartition<TSource> Take(int startIndexInclusive, int endIndexExclusive, bool isStartIndexFromEnd, bool isEndIndexFromEnd);
// Original members.
TSource? TryGetElementAt(int index, out bool found)
{
found = TryGetElementAt(index, false, out TSource? element);
return element;
}
IPartition<TSource> Take(int count) => Take(0, count, false, false);;
IPartition<TSource> Skip(int count) => Take(count, 0, false, true);
// Other members ...
}
- Update all types that implement
IPartition<T>. All optimization code should be in these types, not in the LINQ operators.
EmptyPartition<TElement>
ListPartition<TSource>
EnumerablePartition<TSource>
RangeIterator
RepeatIterator<TResult>
SelectArrayIterator<TSource, TResult>
SelectRangeIterator<TResult>
SelectListIterator<TSource, TResult>
SelectIListIterator<TSource, TResult>
SelectIPartitionIterator<TSource, TResult>
SelectListPartitionIterator<TSource, TResult>
OrderedPartition<TElement>
OrderedEnumerable<TElement, TKey>
- Implement
Enumerable.TakeIterator based on IPartition<T>, then use Enumerable.TakeIterator to implement Take, Skip, TakeLast, SkipLast, Take(System.Range).
- Update
ElementAt(System.Index) to utilize IPartition<T>TryGetElementAt
Then all partition and element APIs should be consolidated, optimized, consistent.
My PR #48559 "Add LINQ APIs for Index and Range" was just merged, and this is a following up. @eiriktsarpalis @stephentoub
Background:
IPartition<T>to optimize the implementation of partitioning operators, likeTake,Skip,ElementAtTakeLast,SkipLast,Take(System.Range),ElementAt(System.Index). These new APIs are implemented byyield return.Proposal
It is best to have an unified implementation of all the partitioning and element operators based on
IPartition<T>.Internal API changes
Current
IPartition<T>:IPartition<T>to support indexes from start or end:IPartition<T>. All optimization code should be in these types, not in the LINQ operators.EmptyPartition<TElement>ListPartition<TSource>EnumerablePartition<TSource>RangeIteratorRepeatIterator<TResult>SelectArrayIterator<TSource, TResult>SelectRangeIterator<TResult>SelectListIterator<TSource, TResult>SelectIListIterator<TSource, TResult>SelectIPartitionIterator<TSource, TResult>SelectListPartitionIterator<TSource, TResult>OrderedPartition<TElement>OrderedEnumerable<TElement, TKey>Enumerable.TakeIteratorbased onIPartition<T>, then useEnumerable.TakeIteratorto implementTake,Skip,TakeLast,SkipLast,Take(System.Range).ElementAt(System.Index)to utilizeIPartition<T>TryGetElementAtThen all partition and element APIs should be consolidated, optimized, consistent.