@@ -20,7 +20,7 @@ namespace Microsoft.Toolkit.HighPerformance.Enumerables
20
20
/// A <see langword="ref"/> <see langword="struct"/> that iterates readonly items from arbitrary memory locations.
21
21
/// </summary>
22
22
/// <typeparam name="T">The type of items to enumerate.</typeparam>
23
- public ref struct ReadOnlyRefEnumerable < T >
23
+ public readonly ref struct ReadOnlyRefEnumerable < T >
24
24
{
25
25
#if SPAN_RUNTIME_SUPPORT
26
26
/// <summary>
@@ -51,24 +51,17 @@ public ref struct ReadOnlyRefEnumerable<T>
51
51
/// <remarks>The distance refers to <typeparamref name="T"/> items, not byte offset.</remarks>
52
52
private readonly int step ;
53
53
54
- /// <summary>
55
- /// The current position in the sequence.
56
- /// </summary>
57
- private int position ;
58
-
59
54
#if SPAN_RUNTIME_SUPPORT
60
55
/// <summary>
61
56
/// Initializes a new instance of the <see cref="ReadOnlyRefEnumerable{T}"/> struct.
62
57
/// </summary>
63
58
/// <param name="span">The <see cref="ReadOnlySpan{T}"/> instance pointing to the first item in the target memory area.</param>
64
59
/// <param name="step">The distance between items in the sequence to enumerate.</param>
65
- /// <param name="position">The current position in the sequence.</param>
66
60
[ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
67
- private ReadOnlyRefEnumerable ( ReadOnlySpan < T > span , int step , int position )
61
+ private ReadOnlyRefEnumerable ( ReadOnlySpan < T > span , int step )
68
62
{
69
63
this . span = span ;
70
64
this . step = step ;
71
- this . position = position ;
72
65
}
73
66
74
67
/// <summary>
@@ -82,27 +75,8 @@ internal ReadOnlyRefEnumerable(in T reference, int length, int step)
82
75
{
83
76
this . span = MemoryMarshal . CreateReadOnlySpan ( ref Unsafe . AsRef ( reference ) , length ) ;
84
77
this . step = step ;
85
- this . position = - 1 ;
86
78
}
87
79
#else
88
- /// <summary>
89
- /// Initializes a new instance of the <see cref="ReadOnlyRefEnumerable{T}"/> struct.
90
- /// </summary>
91
- /// <param name="instance">The target <see cref="object"/> instance.</param>
92
- /// <param name="offset">The initial offset within <see paramref="instance"/>.</param>
93
- /// <param name="length">The number of items in the sequence.</param>
94
- /// <param name="step">The distance between items in the sequence to enumerate.</param>
95
- /// <param name="position">The current position in the sequence.</param>
96
- [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
97
- private ReadOnlyRefEnumerable ( object ? instance , IntPtr offset , int length , int step , int position )
98
- {
99
- this . instance = instance ;
100
- this . offset = offset ;
101
- this . length = length ;
102
- this . step = step ;
103
- this . position = position ;
104
- }
105
-
106
80
/// <summary>
107
81
/// Initializes a new instance of the <see cref="ReadOnlyRefEnumerable{T}"/> struct.
108
82
/// </summary>
@@ -117,42 +91,19 @@ internal ReadOnlyRefEnumerable(object? instance, IntPtr offset, int length, int
117
91
this . offset = offset ;
118
92
this . length = length ;
119
93
this . step = step ;
120
- this . position = - 1 ;
121
94
}
122
95
#endif
123
96
124
97
/// <inheritdoc cref="System.Collections.IEnumerable.GetEnumerator"/>
125
98
[ Pure ]
126
99
[ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
127
- public readonly ReadOnlyRefEnumerable < T > GetEnumerator ( ) => this ;
128
-
129
- /// <inheritdoc cref="System.Collections.IEnumerator.MoveNext"/>
130
- [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
131
- public bool MoveNext ( )
132
- {
133
- #if SPAN_RUNTIME_SUPPORT
134
- return ++ this . position < this . span . Length ;
135
- #else
136
- return ++ this . position < this . length ;
137
- #endif
138
- }
139
-
140
- /// <inheritdoc cref="System.Collections.Generic.IEnumerator{T}.Current"/>
141
- public readonly ref readonly T Current
100
+ public Enumerator GetEnumerator ( )
142
101
{
143
- [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
144
- get
145
- {
146
102
#if SPAN_RUNTIME_SUPPORT
147
- ref T r0 = ref this . span . DangerousGetReference ( ) ;
103
+ return new Enumerator ( this . span , this . step ) ;
148
104
#else
149
- ref T r0 = ref RuntimeHelpers . GetObjectDataAtOffsetOrPointerReference < T > ( this . instance , this . offset ) ;
105
+ return new Enumerator ( this . instance , this . offset , this . length , this . step ) ;
150
106
#endif
151
- nint offset = ( nint ) ( uint ) this . position * ( nint ) ( uint ) this . step ;
152
- ref T ri = ref Unsafe . Add ( ref r0 , offset ) ;
153
-
154
- return ref ri ;
155
- }
156
107
}
157
108
158
109
/// <summary>
@@ -162,7 +113,7 @@ public readonly ref readonly T Current
162
113
/// <exception cref="ArgumentException">
163
114
/// Thrown when <paramref name="destination"/> is shorter than the source <see cref="ReadOnlyRefEnumerable{T}"/> instance.
164
115
/// </exception>
165
- public readonly void CopyTo ( RefEnumerable < T > destination )
116
+ public void CopyTo ( RefEnumerable < T > destination )
166
117
{
167
118
#if SPAN_RUNTIME_SUPPORT
168
119
if ( this . step == 1 )
@@ -205,7 +156,7 @@ public readonly void CopyTo(RefEnumerable<T> destination)
205
156
/// </summary>
206
157
/// <param name="destination">The target <see cref="RefEnumerable{T}"/> of the copy operation.</param>
207
158
/// <returns>Whether or not the operation was successful.</returns>
208
- public readonly bool TryCopyTo ( RefEnumerable < T > destination )
159
+ public bool TryCopyTo ( RefEnumerable < T > destination )
209
160
{
210
161
#if SPAN_RUNTIME_SUPPORT
211
162
int
@@ -234,7 +185,7 @@ public readonly bool TryCopyTo(RefEnumerable<T> destination)
234
185
/// <exception cref="ArgumentException">
235
186
/// Thrown when <paramref name="destination"/> is shorter than the source <see cref="RefEnumerable{T}"/> instance.
236
187
/// </exception>
237
- public readonly void CopyTo ( Span < T > destination )
188
+ public void CopyTo ( Span < T > destination )
238
189
{
239
190
#if SPAN_RUNTIME_SUPPORT
240
191
if ( this . step == 1 )
@@ -265,7 +216,7 @@ public readonly void CopyTo(Span<T> destination)
265
216
/// </summary>
266
217
/// <param name="destination">The target <see cref="Span{T}"/> of the copy operation.</param>
267
218
/// <returns>Whether or not the operation was successful.</returns>
268
- public readonly bool TryCopyTo ( Span < T > destination )
219
+ public bool TryCopyTo ( Span < T > destination )
269
220
{
270
221
#if SPAN_RUNTIME_SUPPORT
271
222
int length = this . span . Length ;
@@ -285,7 +236,7 @@ public readonly bool TryCopyTo(Span<T> destination)
285
236
286
237
/// <inheritdoc cref="RefEnumerable{T}.ToArray"/>
287
238
[ Pure ]
288
- public readonly T [ ] ToArray ( )
239
+ public T [ ] ToArray ( )
289
240
{
290
241
#if SPAN_RUNTIME_SUPPORT
291
242
int length = this . span . Length ;
@@ -314,10 +265,99 @@ public readonly T[] ToArray()
314
265
public static implicit operator ReadOnlyRefEnumerable < T > ( RefEnumerable < T > enumerable )
315
266
{
316
267
#if SPAN_RUNTIME_SUPPORT
317
- return new ReadOnlyRefEnumerable < T > ( enumerable . Span , enumerable . Step , enumerable . Position ) ;
268
+ return new ReadOnlyRefEnumerable < T > ( enumerable . Span , enumerable . Step ) ;
269
+ #else
270
+ return new ReadOnlyRefEnumerable < T > ( enumerable . Instance , enumerable . Offset , enumerable . Length , enumerable . Step ) ;
271
+ #endif
272
+ }
273
+
274
+ /// <summary>
275
+ /// A custom enumerator type to traverse items within a <see cref="ReadOnlyRefEnumerable{T}"/> instance.
276
+ /// </summary>
277
+ public ref struct Enumerator
278
+ {
279
+ #if SPAN_RUNTIME_SUPPORT
280
+ /// <inheritdoc cref="ReadOnlyRefEnumerable{T}.span"/>
281
+ private readonly ReadOnlySpan < T > span ;
318
282
#else
319
- return new ReadOnlyRefEnumerable < T > ( enumerable . Instance , enumerable . Offset , enumerable . Length , enumerable . Step , enumerable . Position ) ;
283
+ /// <inheritdoc cref="ReadOnlyRefEnumerable{T}.instance"/>
284
+ private readonly object ? instance ;
285
+
286
+ /// <inheritdoc cref="ReadOnlyRefEnumerable{T}.offset"/>
287
+ private readonly IntPtr offset ;
288
+
289
+ /// <inheritdoc cref="ReadOnlyRefEnumerable{T}.length"/>
290
+ private readonly int length ;
320
291
#endif
292
+
293
+ /// <inheritdoc cref="ReadOnlyRefEnumerable{T}.step"/>
294
+ private readonly int step ;
295
+
296
+ /// <summary>
297
+ /// The current position in the sequence.
298
+ /// </summary>
299
+ private int position ;
300
+
301
+ #if SPAN_RUNTIME_SUPPORT
302
+ /// <summary>
303
+ /// Initializes a new instance of the <see cref="Enumerator"/> struct.
304
+ /// </summary>
305
+ /// <param name="span">The <see cref="ReadOnlySpan{T}"/> instance with the info on the items to traverse.</param>
306
+ /// <param name="step">The distance between items in the sequence to enumerate.</param>
307
+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
308
+ internal Enumerator ( ReadOnlySpan < T > span , int step )
309
+ {
310
+ this . span = span ;
311
+ this . step = step ;
312
+ this . position = - 1 ;
313
+ }
314
+ #else
315
+ /// <summary>
316
+ /// Initializes a new instance of the <see cref="Enumerator"/> struct.
317
+ /// </summary>
318
+ /// <param name="instance">The target <see cref="object"/> instance.</param>
319
+ /// <param name="offset">The initial offset within <see paramref="instance"/>.</param>
320
+ /// <param name="length">The number of items in the sequence.</param>
321
+ /// <param name="step">The distance between items in the sequence to enumerate.</param>
322
+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
323
+ internal Enumerator ( object ? instance , IntPtr offset , int length , int step )
324
+ {
325
+ this . instance = instance ;
326
+ this . offset = offset ;
327
+ this . length = length ;
328
+ this . step = step ;
329
+ this . position = - 1 ;
330
+ }
331
+ #endif
332
+
333
+ /// <inheritdoc cref="System.Collections.IEnumerator.MoveNext"/>
334
+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
335
+ public bool MoveNext ( )
336
+ {
337
+ #if SPAN_RUNTIME_SUPPORT
338
+ return ++ this . position < this . span . Length ;
339
+ #else
340
+ return ++ this . position < this . length ;
341
+ #endif
342
+ }
343
+
344
+ /// <inheritdoc cref="System.Collections.Generic.IEnumerator{T}.Current"/>
345
+ public readonly ref readonly T Current
346
+ {
347
+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
348
+ get
349
+ {
350
+ #if SPAN_RUNTIME_SUPPORT
351
+ ref T r0 = ref this . span . DangerousGetReference ( ) ;
352
+ #else
353
+ ref T r0 = ref RuntimeHelpers . GetObjectDataAtOffsetOrPointerReference < T > ( this . instance , this . offset ) ;
354
+ #endif
355
+ nint offset = ( nint ) ( uint ) this . position * ( nint ) ( uint ) this . step ;
356
+ ref T ri = ref Unsafe . Add ( ref r0 , offset ) ;
357
+
358
+ return ref ri ;
359
+ }
360
+ }
321
361
}
322
362
323
363
/// <summary>
0 commit comments