Return singleton enumerators from IEnumerable.GetEnumerator for empty collections...
authorStephen Toub <stoub@microsoft.com>
Thu, 23 Feb 2023 23:00:59 +0000 (18:00 -0500)
committerGitHub <noreply@github.com>
Thu, 23 Feb 2023 23:00:59 +0000 (18:00 -0500)
commitdc6ad37d410931edb6b46203fb73d6503ed29dc8
treeb5a230d8b11755e341aa295844d9c96f7fb62a7c
parentf8b9b8dd2b2e65353bbf0b43f304633aa5b66d19
Return singleton enumerators from IEnumerable.GetEnumerator for empty collections (#82499)

* Return singleton enumerators from IEnumerable.GetEnumerator for empty 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.

* Address PR feedback

- Create helper function for empty enumerator
- Add tests for singletons

* Fix a few tests
45 files changed:
src/libraries/Common/src/System/Collections/Generic/EnumerableHelpers.cs
src/libraries/Common/tests/System/Collections/IDictionary.Generic.Tests.cs
src/libraries/Common/tests/System/Collections/IDictionary.NonGeneric.Tests.cs
src/libraries/Common/tests/System/Collections/IEnumerable.Generic.Tests.cs
src/libraries/Common/tests/System/Collections/IEnumerable.NonGeneric.Tests.cs
src/libraries/Common/tests/System/Collections/IList.Generic.Tests.cs
src/libraries/System.Collections.Concurrent/tests/ConcurrentDictionary/ConcurrentDictionary.Generic.Tests.cs
src/libraries/System.Collections.Concurrent/tests/ConcurrentDictionary/ConcurrentDictionary.NonGeneric.Tests.cs
src/libraries/System.Collections.Immutable/tests/ImmutableArray/ImmutableArray.Generic.Tests.cs
src/libraries/System.Collections.Immutable/tests/ImmutableArray/ImmutableArray.NonGeneric.Tests.cs
src/libraries/System.Collections/src/System/Collections/Generic/LinkedList.cs
src/libraries/System.Collections/src/System/Collections/Generic/PriorityQueue.cs
src/libraries/System.Collections/src/System/Collections/Generic/SortedDictionary.cs
src/libraries/System.Collections/src/System/Collections/Generic/SortedList.cs
src/libraries/System.Collections/src/System/Collections/Generic/SortedSet.cs
src/libraries/System.Collections/src/System/Collections/Generic/Stack.cs
src/libraries/System.Collections/tests/Generic/Dictionary/Dictionary.Generic.Tests.Keys.cs
src/libraries/System.Collections/tests/Generic/Dictionary/Dictionary.Generic.Tests.Values.cs
src/libraries/System.Collections/tests/Generic/Dictionary/Dictionary.Generic.Tests.cs
src/libraries/System.Collections/tests/Generic/Dictionary/Dictionary.Tests.cs
src/libraries/System.Collections/tests/Generic/HashSet/HashSet.Generic.Tests.AsNonGenericIEnumerable.cs
src/libraries/System.Collections/tests/Generic/HashSet/HashSet.Generic.Tests.cs
src/libraries/System.Collections/tests/Generic/LinkedList/LinkedList.Generic.Tests.AsNonGenericICollection.cs
src/libraries/System.Collections/tests/Generic/LinkedList/LinkedList.Generic.Tests.cs
src/libraries/System.Collections/tests/Generic/List/List.Generic.Tests.cs
src/libraries/System.Collections/tests/Generic/Queue/Queue.Generic.Tests.cs
src/libraries/System.Collections/tests/Generic/Queue/Queue.Tests.cs
src/libraries/System.Collections/tests/Generic/SortedDictionary/SortedDictionary.Generic.Tests.Keys.cs
src/libraries/System.Collections/tests/Generic/SortedDictionary/SortedDictionary.Generic.Tests.Values.cs
src/libraries/System.Collections/tests/Generic/SortedDictionary/SortedDictionary.Generic.Tests.cs
src/libraries/System.Collections/tests/Generic/SortedDictionary/SortedDictionary.Tests.cs
src/libraries/System.Collections/tests/Generic/SortedList/SortedList.Generic.Tests.Keys.cs
src/libraries/System.Collections/tests/Generic/SortedList/SortedList.Generic.Tests.Values.cs
src/libraries/System.Collections/tests/Generic/SortedList/SortedList.Generic.Tests.cs
src/libraries/System.Collections/tests/Generic/SortedList/SortedList.Tests.cs
src/libraries/System.Collections/tests/Generic/Stack/Stack.Generic.Tests.cs
src/libraries/System.Collections/tests/Generic/Stack/Stack.Tests.cs
src/libraries/System.Private.CoreLib/src/System/ArraySegment.cs
src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Dictionary.cs
src/libraries/System.Private.CoreLib/src/System/Collections/Generic/HashSet.cs
src/libraries/System.Private.CoreLib/src/System/Collections/Generic/List.cs
src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Queue.cs
src/libraries/System.Private.CoreLib/src/System/Collections/ObjectModel/ReadOnlyCollection.cs
src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/ConditionalWeakTable.cs
src/libraries/System.Runtime/tests/System/ArraySegmentTests.cs