Enable non-allocating enumeration via collection interfaces #5246
+638
−5
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Bug
Fixes: NuGet/Home#12679
Regression? Last working version: N/A
Description
Interfaces like
IEnumerable<T>
,IList<T>
andIDictionary<TKey, TValue>
are used in many APIs. The upside of this is that the implementation of these APIs may change the concrete type of the collection as it sees fit without breaking consumers. The downside of this is that some operations through the interface are more expensive than if they were performed directly on the concrete type. Enumeration is perhaps the biggest challege here, as enumerating through these interfaces withforeach
always requires a heap allocation.Most concrete implementations these implementations will be types such as
List<T>
andDictionary<TKey,TValue>
which have a non-allocating struct enumerators.Specifically:
This change adds
NoAllocEnumerate()
extension methods that avoid any enumerator allocation when the concrete collection type is known to have such a struct enumerator at runtime.Note that this pattern can be extended to other commonly enumerated types that have struct enumerators. Here it's specialized for
IEnumerable<T>
,IList<T>
andIDictionary<TKey,TValue>
in order to limit the number of struct enumerators needed on the structs themselves. It seems like NuGet.Client mostly usesList<T>
andDictionary<TKey,TValue>
(as opposed to other collections likeImmutableArray<T>
,ImmutableList<T>
,ImmutableDictionary<TKey,TValue>
, etc.). The list of supported types can be extended as investigations and investment in this area continue.PR Checklist
PR has a meaningful title
PR has a linked issue.
Described changes
Tests
Documentation