-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Closed
Labels
Milestone
Description
Turns out the world is full of empty collections. Empty lists, empty dictionaries, empty sets. The world is also full of code that ends up enumerating these empty collections. And if this code happens to hold an interface type such as IList<T> or IReadOnlyList<T>, then enumerating these empty collections causes a heap allocation:
IReadOnlyList<int> l = new List<int>();
foreach (var foo in l) // <-- allocates an enumerator, *sigh*
{
}It should be possible to eliminate these allocations by adding a teeny bit of logic to the collection types. For example, consider List<T>:
public class List<T>
{
IEnumerator<T> IEnumerable<T>.GetEnumerator()
=> (_size == 0) ? _staticEmptyEnumerator : new Enumerator(this);
private static readonly EmptyEnumerator _staticEmptyEnumerator = new ();
private sealed class EmptyEnumerator : IEnumerator<T>
{
public void Dispose() {}
public bool MoveNext() => false;
public void Reset() {}
public T Current => throw new NotSupportedException();
object IEnumerator.Current => throw new NotSupportedException();
}
}The above code detects if the collection is empty and then returns a static enumerator instance to the caller. No allocation occurs, the world is a slightly better place as a result.
airbreather, Enderlook and Rekkonnect