Skip to content

Commit f3e7e00

Browse files
committed
Minor code refactoring
1 parent 20bd65f commit f3e7e00

File tree

2 files changed

+210
-118
lines changed

2 files changed

+210
-118
lines changed

Microsoft.Toolkit.HighPerformance/Enumerables/ReadOnlyRefEnumerable{T}.cs

Lines changed: 101 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ namespace Microsoft.Toolkit.HighPerformance.Enumerables
2020
/// A <see langword="ref"/> <see langword="struct"/> that iterates readonly items from arbitrary memory locations.
2121
/// </summary>
2222
/// <typeparam name="T">The type of items to enumerate.</typeparam>
23-
public ref struct ReadOnlyRefEnumerable<T>
23+
public readonly ref struct ReadOnlyRefEnumerable<T>
2424
{
2525
#if SPAN_RUNTIME_SUPPORT
2626
/// <summary>
@@ -51,24 +51,17 @@ public ref struct ReadOnlyRefEnumerable<T>
5151
/// <remarks>The distance refers to <typeparamref name="T"/> items, not byte offset.</remarks>
5252
private readonly int step;
5353

54-
/// <summary>
55-
/// The current position in the sequence.
56-
/// </summary>
57-
private int position;
58-
5954
#if SPAN_RUNTIME_SUPPORT
6055
/// <summary>
6156
/// Initializes a new instance of the <see cref="ReadOnlyRefEnumerable{T}"/> struct.
6257
/// </summary>
6358
/// <param name="span">The <see cref="ReadOnlySpan{T}"/> instance pointing to the first item in the target memory area.</param>
6459
/// <param name="step">The distance between items in the sequence to enumerate.</param>
65-
/// <param name="position">The current position in the sequence.</param>
6660
[MethodImpl(MethodImplOptions.AggressiveInlining)]
67-
private ReadOnlyRefEnumerable(ReadOnlySpan<T> span, int step, int position)
61+
private ReadOnlyRefEnumerable(ReadOnlySpan<T> span, int step)
6862
{
6963
this.span = span;
7064
this.step = step;
71-
this.position = position;
7265
}
7366

7467
/// <summary>
@@ -82,27 +75,8 @@ internal ReadOnlyRefEnumerable(in T reference, int length, int step)
8275
{
8376
this.span = MemoryMarshal.CreateReadOnlySpan(ref Unsafe.AsRef(reference), length);
8477
this.step = step;
85-
this.position = -1;
8678
}
8779
#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-
10680
/// <summary>
10781
/// Initializes a new instance of the <see cref="ReadOnlyRefEnumerable{T}"/> struct.
10882
/// </summary>
@@ -117,42 +91,19 @@ internal ReadOnlyRefEnumerable(object? instance, IntPtr offset, int length, int
11791
this.offset = offset;
11892
this.length = length;
11993
this.step = step;
120-
this.position = -1;
12194
}
12295
#endif
12396

12497
/// <inheritdoc cref="System.Collections.IEnumerable.GetEnumerator"/>
12598
[Pure]
12699
[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()
142101
{
143-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
144-
get
145-
{
146102
#if SPAN_RUNTIME_SUPPORT
147-
ref T r0 = ref this.span.DangerousGetReference();
103+
return new Enumerator(this.span, this.step);
148104
#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);
150106
#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-
}
156107
}
157108

158109
/// <summary>
@@ -162,7 +113,7 @@ public readonly ref readonly T Current
162113
/// <exception cref="ArgumentException">
163114
/// Thrown when <paramref name="destination"/> is shorter than the source <see cref="ReadOnlyRefEnumerable{T}"/> instance.
164115
/// </exception>
165-
public readonly void CopyTo(RefEnumerable<T> destination)
116+
public void CopyTo(RefEnumerable<T> destination)
166117
{
167118
#if SPAN_RUNTIME_SUPPORT
168119
if (this.step == 1)
@@ -205,7 +156,7 @@ public readonly void CopyTo(RefEnumerable<T> destination)
205156
/// </summary>
206157
/// <param name="destination">The target <see cref="RefEnumerable{T}"/> of the copy operation.</param>
207158
/// <returns>Whether or not the operation was successful.</returns>
208-
public readonly bool TryCopyTo(RefEnumerable<T> destination)
159+
public bool TryCopyTo(RefEnumerable<T> destination)
209160
{
210161
#if SPAN_RUNTIME_SUPPORT
211162
int
@@ -234,7 +185,7 @@ public readonly bool TryCopyTo(RefEnumerable<T> destination)
234185
/// <exception cref="ArgumentException">
235186
/// Thrown when <paramref name="destination"/> is shorter than the source <see cref="RefEnumerable{T}"/> instance.
236187
/// </exception>
237-
public readonly void CopyTo(Span<T> destination)
188+
public void CopyTo(Span<T> destination)
238189
{
239190
#if SPAN_RUNTIME_SUPPORT
240191
if (this.step == 1)
@@ -265,7 +216,7 @@ public readonly void CopyTo(Span<T> destination)
265216
/// </summary>
266217
/// <param name="destination">The target <see cref="Span{T}"/> of the copy operation.</param>
267218
/// <returns>Whether or not the operation was successful.</returns>
268-
public readonly bool TryCopyTo(Span<T> destination)
219+
public bool TryCopyTo(Span<T> destination)
269220
{
270221
#if SPAN_RUNTIME_SUPPORT
271222
int length = this.span.Length;
@@ -285,7 +236,7 @@ public readonly bool TryCopyTo(Span<T> destination)
285236

286237
/// <inheritdoc cref="RefEnumerable{T}.ToArray"/>
287238
[Pure]
288-
public readonly T[] ToArray()
239+
public T[] ToArray()
289240
{
290241
#if SPAN_RUNTIME_SUPPORT
291242
int length = this.span.Length;
@@ -314,10 +265,99 @@ public readonly T[] ToArray()
314265
public static implicit operator ReadOnlyRefEnumerable<T>(RefEnumerable<T> enumerable)
315266
{
316267
#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;
318282
#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;
320291
#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+
}
321361
}
322362

323363
/// <summary>

0 commit comments

Comments
 (0)