Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public void Reset()
}
}

internal class SZGenericArrayEnumeratorBase
internal abstract class SZGenericArrayEnumeratorBase
{
protected readonly Array _array;
protected int _index;
Expand Down Expand Up @@ -104,10 +104,17 @@ public void Dispose()

internal sealed class SZGenericArrayEnumerator<T> : SZGenericArrayEnumeratorBase, IEnumerator<T>
{
// Array.Empty is intentionally omitted here, since we don't want to pay for generic instantiations that
// wouldn't have otherwise been used.
/// <summary>Provides an empty enumerator singleton.</summary>
/// <remarks>
/// If the consumer is using SZGenericArrayEnumerator elsewhere or is otherwise likely
/// to be using T[] elsewhere, this singleton should be used. Otherwise, GenericEmptyEnumerator's
/// singleton should be used instead, as it doesn't reference T[] in order to reduce footprint.
/// </remarks>
#pragma warning disable CA1825
internal static readonly SZGenericArrayEnumerator<T> Empty = new SZGenericArrayEnumerator<T>(new T[0]);
internal static readonly SZGenericArrayEnumerator<T> Empty =
// Array.Empty is intentionally omitted here, since we don't want to pay for generic instantiations
// that wouldn't have otherwise been used.
new SZGenericArrayEnumerator<T>(new T[0]);
#pragma warning restore CA1825

public SZGenericArrayEnumerator(T[] array)
Expand All @@ -133,4 +140,46 @@ public T Current

object? IEnumerator.Current => Current;
}

internal abstract class GenericEmptyEnumeratorBase
{
#pragma warning disable CA1822 // https://github.com/dotnet/roslyn-analyzers/issues/5911
public bool MoveNext() => false;

public object Current
{
get
{
ThrowHelper.ThrowInvalidOperationException_EnumCurrent(-1);
return default;
}
}

public void Reset() { }

public void Dispose() { }
#pragma warning restore CA1822
}

/// <summary>Provides an empty enumerator singleton.</summary>
/// <remarks>
/// If the consumer is using SZGenericArrayEnumerator elsewhere or is otherwise likely
/// to be using T[] elsewhere, SZGenericArrayEnumerator's singleton should be used. Otherwise,
/// this singleton should be used, as it doesn't reference T[] in order to reduce footprint.
/// </remarks>
internal sealed class GenericEmptyEnumerator<T> : GenericEmptyEnumeratorBase, IEnumerator<T>
{
public static readonly GenericEmptyEnumerator<T> Instance = new();

private GenericEmptyEnumerator() { }

public new T Current
{
get
{
ThrowHelper.ThrowInvalidOperationException_EnumCurrent(-1);
return default;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ private void CopyTo(KeyValuePair<TKey, TValue>[] array, int index)
public Enumerator GetEnumerator() => new Enumerator(this, Enumerator.KeyValuePair);

IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator() =>
Count == 0 ? SZGenericArrayEnumerator<KeyValuePair<TKey, TValue>>.Empty :
Count == 0 ? GenericEmptyEnumerator<KeyValuePair<TKey, TValue>>.Instance :
GetEnumerator();

public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.
{
Container c = _container;
return c is null || c.FirstFreeEntry == 0 ?
SZGenericArrayEnumerator<KeyValuePair<TKey, TValue>>.Empty :
GenericEmptyEnumerator<KeyValuePair<TKey, TValue>>.Instance :
new Enumerator(this);
}
}
Expand Down