Return singleton enumerators from IEnumerable.GetEnumerator for empty collections#82499
Conversation
… collections Change the `IEnumerable<T>.GetEnumerator()` implementations on our core collection types to special-case Count==0 in order to return a single enumerator instead of allocating one a new each time. This saves an allocation when enumerating these collections via the interface in exchange for an extra length check as part of GetEnumerator.
|
Tagging subscribers to this area: @dotnet/area-system-collections Issue DetailsChange the This changes Fixes #59596 Relates to #81523, as this means that code like: var list = new List<int>();
IEnumerator<int> e = list.GetEnumerator();
list.Add(42);
e.MoveNext();which would previously have thrown an exception on the
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
using System.Collections.Generic;
[MemoryDiagnoser(false)]
public partial class Program
{
static void Main(string[] args) => BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args);
private IEnumerable<int> _empty = new List<int>();
private IEnumerable<int> _one = new List<int>() { 42 };
[Benchmark]
public int SumEmpty()
{
int sum = 0;
foreach (int i in _empty) sum += i;
return sum;
}
[Benchmark]
public int SumOne()
{
int sum = 0;
foreach (int i in _one) sum += i;
return sum;
}
}
|
src/libraries/System.Collections/src/System/Collections/Generic/PriorityQueue.cs
Outdated
Show resolved
Hide resolved
src/libraries/Common/tests/System/Collections/IList.Generic.Tests.cs
Outdated
Show resolved
Hide resolved
- Create helper function for empty enumerator - Add tests for singletons
edc544e to
a5329bf
Compare
Change the
IEnumerable<T>.GetEnumerator()implementations on our core collection types to special-case Count==0 in order to return a single enumerator instead of allocating one a new each time. This saves an allocation when enumerating these collections via the interface in exchange for an extra length check as part of GetEnumerator.This changes
List<>,Queue<>,Stack<>,LinkedList<>,PriorityQueue<,>,SortedDictionary<,>,SortedList<,>,SortedSet<>,HashSet<>,Dictionary<,>, andArraySegment<>.Fixes #59596
Relates to #81523, as this means that code like:
which would previously have thrown an exception on the
MoveNextcall will no longer throw an exception.