Reputation:
I had a look at the .NET Core source in order to find out whether calls to IEnumerable.Last()
(LINQ) are optimized when the collection implements IList
which I suspected to be the case after some quick benchmarking. It turns out that yes, the input is specifically checked for IList
, however, even before that, it is checked whether the input implements IPartition
. IPartition
is defined here, but I do not understand at all what it is supposed to do.
What is the purpose of IPartition
and how could it possibly be faster than the usually constant-time indexing of IList
(or if it isn't, why is the input checked for IPartition
earlier than IList
)?
Upvotes: 8
Views: 1148
Reputation: 171246
It's an optimization for enumerable methods that act on indexes (Take/Skip and others) when the collection has support for indexes. IIListProvider
is related.
There are a few implementations. Search the file for IPartition
.
There are issues about this.
IPartition
allows to delegate higher level operations to the underlying collection. For example, new int[10].Skip(1)
is slow because all data runs through two IEnumerable<int>
. With the IPartition
implementation this turns into effectively for (int i = 1 ... 9) emit(list[i]);
. So it's not using intermediate enumerators and it's calling the list indexer which is slightly faster than enumerating.
This is a very rough description. I encourage you to check out the Github discussions and the code.
Upvotes: 8