@@ -82,12 +82,22 @@ public class BlitzMap<TKey, TValue, THasher> where THasher : struct, IHasher<TKe
8282 #region Enumerable
8383
8484 /// <summary>
85- /// Fallback for `foreach` compatibility.
85+ /// Fallback for `foreach` compatibility.
86+ /// Example:
87+ /// <code>
88+ /// foreach (ref readonly var entry in map)
89+ /// {
90+ ///
91+ /// }
92+ /// </code>
8693 /// </summary>
8794 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
88- public IEnumerator < Entry > GetEnumerator ( )
95+ public SpanEnumerator GetEnumerator ( )
8996 {
90- return new FastEnumerator ( _entries , ( int ) _count ) ;
97+ return new SpanEnumerator (
98+ MemoryMarshal . CreateReadOnlySpan (
99+ ref MemoryMarshal . GetArrayDataReference ( _entries ) ,
100+ ( int ) _count ) ) ;
91101 }
92102
93103 #endregion
@@ -107,7 +117,7 @@ public IEnumerator<Entry> GetEnumerator()
107117 private uint _maxCountBeforeResize ;
108118 private THasher _hasher ;
109119 private uint _lastBucket = INACTIVE ;
110-
120+
111121 #endregion
112122 /// <summary>
113123 /// Initializes a new instance of the <see cref="BlitzMap{TKey, TValue, THasher}"/> class
@@ -951,62 +961,35 @@ public struct Bucket
951961 public uint Next ;
952962 }
953963
954- public unsafe struct FastEnumerator : IEnumerator < Entry >
964+ public ref struct SpanEnumerator
955965 {
956- private readonly Entry * _start ;
957- private readonly Entry * _end ;
958- private Entry * _current ;
966+ private ReadOnlySpan < Entry > _span ;
967+ private int _index ;
959968
960- /// <summary>
961- /// Initializes a new instance of the <see cref="FastEnumerator"/> struct.
962- /// Uses unsafe pointer-based iteration for extreme performance.
963- /// </summary>
964- /// <param name="entries">The array of entries to enumerate.</param>
965- /// <param name="length">The number of elements in the array.</param>
966969 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
967- public FastEnumerator ( Entry [ ] entries , int length )
970+ public SpanEnumerator ( ReadOnlySpan < Entry > span )
968971 {
969- // Convert array reference to a raw pointer (avoiding fixed blocks)
970- _start = ( Entry * ) Unsafe . AsPointer ( ref MemoryMarshal . GetArrayDataReference ( entries ) ) ;
971- _end = _start + length ; // Pointer to the end of the array
972- _current = _start - 1 ; // Start before the first element (MoveNext() advances it)
972+ _span = span ;
973+ _index = - 1 ;
973974 }
974975
975- /// <summary>
976- /// Moves to the next element in the collection.
977- /// </summary>
978- /// <returns>True if the enumerator successfully moved to the next element, false if at the end.</returns>
979976 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
980977 public bool MoveNext ( )
981978 {
982- _current ++ ; // Move pointer to the next entry
983- return _current < _end ; // Check if within bounds
979+ int next = _index + 1 ;
980+ if ( next < _span . Length )
981+ {
982+ _index = next ;
983+ return true ;
984+ }
985+ return false ;
984986 }
985987
986- /// <summary>
987- /// Gets the current entry in the enumeration.
988- /// </summary>
989- public readonly Entry Current
988+ public ref readonly Entry Current
990989 {
991990 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
992- get => * _current ; // Dereference pointer to get the current element
991+ get => ref _span [ _index ] ;
993992 }
994-
995- /// <summary>
996- /// Gets the current element of the collection (explicit interface implementation).
997- /// </summary>
998- object IEnumerator . Current => Current ;
999-
1000- /// <summary>
1001- /// Resets the enumerator to its initial position before the first element.
1002- /// </summary>
1003- [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
1004- public void Reset ( ) => _current = _start - 1 ;
1005-
1006- /// <summary>
1007- /// Releases resources used by the enumerator (not needed for structs).
1008- /// </summary>
1009- public void Dispose ( ) { }
1010993 }
1011994
1012995 #endregion
0 commit comments