@@ -21,7 +21,17 @@ namespace CommunityToolkit.HighPerformance.Enumerables;
21
21
/// <typeparam name="T">The type of items to enumerate.</typeparam>
22
22
public readonly ref struct ReadOnlyRefEnumerable < T >
23
23
{
24
- #if NETSTANDARD2_1_OR_GREATER
24
+ #if NET7_0_OR_GREATER
25
+ /// <summary>
26
+ /// The <typeparamref name="T"/> reference for the <see cref="ReadOnlyRefEnumerable{T}"/> instance.
27
+ /// </summary>
28
+ private readonly ref readonly T reference ;
29
+
30
+ /// <summary>
31
+ /// The length of the current sequence.
32
+ /// </summary>
33
+ private readonly int length ;
34
+ #elif NETSTANDARD2_1_OR_GREATER
25
35
/// <summary>
26
36
/// The <see cref="ReadOnlySpan{T}"/> instance pointing to the first item in the target memory area.
27
37
/// </summary>
@@ -51,6 +61,7 @@ public readonly ref struct ReadOnlyRefEnumerable<T>
51
61
private readonly int step ;
52
62
53
63
#if NETSTANDARD2_1_OR_GREATER
64
+ #if ! NET7_0_OR_GREATER
54
65
/// <summary>
55
66
/// Initializes a new instance of the <see cref="ReadOnlyRefEnumerable{T}"/> struct.
56
67
/// </summary>
@@ -59,9 +70,15 @@ public readonly ref struct ReadOnlyRefEnumerable<T>
59
70
[ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
60
71
private ReadOnlyRefEnumerable ( ReadOnlySpan < T > span , int step )
61
72
{
73
+ #if NET7_0_OR_GREATER
74
+ this . reference = ref MemoryMarshal . GetReference ( span ) ;
75
+ this . length = span . Length ;
76
+ #else
62
77
this . span = span ;
78
+ #endif
63
79
this . step = step ;
64
80
}
81
+ #endif
65
82
66
83
/// <summary>
67
84
/// Initializes a new instance of the <see cref="ReadOnlyRefEnumerable{T}"/> struct.
@@ -72,8 +89,14 @@ private ReadOnlyRefEnumerable(ReadOnlySpan<T> span, int step)
72
89
[ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
73
90
internal ReadOnlyRefEnumerable ( in T reference , int length , int step )
74
91
{
92
+ #if NET7_0_OR_GREATER
93
+ this . reference = ref reference ;
94
+ this . length = length ;
95
+ this . step = step ;
96
+ #else
75
97
this . span = MemoryMarshal . CreateReadOnlySpan ( ref Unsafe . AsRef ( reference ) , length ) ;
76
98
this . step = step ;
99
+ #endif
77
100
}
78
101
79
102
/// <summary>
@@ -124,7 +147,9 @@ internal ReadOnlyRefEnumerable(object? instance, IntPtr offset, int length, int
124
147
public int Length
125
148
{
126
149
[ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
127
- #if NETSTANDARD2_1_OR_GREATER
150
+ #if NET7_0_OR_GREATER
151
+ get => this . length ;
152
+ #elif NETSTANDARD2_1_OR_GREATER
128
153
get => this . span . Length ;
129
154
#else
130
155
get => this . length ;
@@ -149,7 +174,9 @@ public ref readonly T this[int index]
149
174
ThrowHelper . ThrowIndexOutOfRangeException ( ) ;
150
175
}
151
176
152
- #if NETSTANDARD2_1_OR_GREATER
177
+ #if NET7_0_OR_GREATER
178
+ ref T r0 = ref Unsafe . AsRef ( in this . reference ) ;
179
+ #elif NETSTANDARD2_1_OR_GREATER
153
180
ref T r0 = ref MemoryMarshal . GetReference ( this . span ) ;
154
181
#else
155
182
ref T r0 = ref RuntimeHelpers . GetObjectDataAtOffsetOrPointerReference < T > ( this . instance , this . offset ) ;
@@ -181,7 +208,9 @@ public ref readonly T this[Index index]
181
208
[ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
182
209
public Enumerator GetEnumerator ( )
183
210
{
184
- #if NETSTANDARD2_1_OR_GREATER
211
+ #if NET7_0_OR_GREATER
212
+ return new ( in this . reference , this . length , this . step ) ;
213
+ #elif NETSTANDARD2_1_OR_GREATER
185
214
return new ( this . span , this . step ) ;
186
215
#else
187
216
return new ( this . instance , this . offset , this . length , this . step ) ;
@@ -197,7 +226,26 @@ public Enumerator GetEnumerator()
197
226
/// </exception>
198
227
public void CopyTo ( RefEnumerable < T > destination )
199
228
{
200
- #if NETSTANDARD2_1_OR_GREATER
229
+ #if NET7_0_OR_GREATER
230
+ if ( this . step == 1 )
231
+ {
232
+ destination . CopyFrom ( MemoryMarshal . CreateReadOnlySpan ( ref Unsafe . AsRef ( in this . reference ) , this . length ) ) ;
233
+
234
+ return ;
235
+ }
236
+
237
+ if ( destination . Step == 1 )
238
+ {
239
+ CopyTo ( MemoryMarshal . CreateSpan ( ref destination . Reference , destination . Length ) ) ;
240
+
241
+ return ;
242
+ }
243
+
244
+ ref T sourceRef = ref Unsafe . AsRef ( in this . reference ) ;
245
+ ref T destinationRef = ref destination . Reference ;
246
+ int sourceLength = this . length ;
247
+ int destinationLength = destination . Length ;
248
+ #elif NETSTANDARD2_1_OR_GREATER
201
249
if ( this . step == 1 )
202
250
{
203
251
destination . CopyFrom ( this . span ) ;
@@ -238,7 +286,10 @@ public void CopyTo(RefEnumerable<T> destination)
238
286
/// <returns>Whether or not the operation was successful.</returns>
239
287
public bool TryCopyTo ( RefEnumerable < T > destination )
240
288
{
241
- #if NETSTANDARD2_1_OR_GREATER
289
+ #if NET7_0_OR_GREATER
290
+ int sourceLength = this . length ;
291
+ int destinationLength = destination . Length ;
292
+ #elif NETSTANDARD2_1_OR_GREATER
242
293
int sourceLength = this . span . Length ;
243
294
int destinationLength = destination . Span . Length ;
244
295
#else
@@ -265,7 +316,17 @@ public bool TryCopyTo(RefEnumerable<T> destination)
265
316
/// </exception>
266
317
public void CopyTo ( Span < T > destination )
267
318
{
268
- #if NETSTANDARD2_1_OR_GREATER
319
+ #if NET7_0_OR_GREATER
320
+ if ( this . step == 1 )
321
+ {
322
+ MemoryMarshal . CreateReadOnlySpan ( ref Unsafe . AsRef ( in this . reference ) , this . length ) . CopyTo ( destination ) ;
323
+
324
+ return ;
325
+ }
326
+
327
+ ref T sourceRef = ref Unsafe . AsRef ( in this . reference ) ;
328
+ int length = this . length ;
329
+ #elif NETSTANDARD2_1_OR_GREATER
269
330
if ( this . step == 1 )
270
331
{
271
332
this . span . CopyTo ( destination ) ;
@@ -296,7 +357,9 @@ public void CopyTo(Span<T> destination)
296
357
/// <returns>Whether or not the operation was successful.</returns>
297
358
public bool TryCopyTo ( Span < T > destination )
298
359
{
299
- #if NETSTANDARD2_1_OR_GREATER
360
+ #if NET7_0_OR_GREATER
361
+ int length = this . length ;
362
+ #elif NETSTANDARD2_1_OR_GREATER
300
363
int length = this . span . Length ;
301
364
#else
302
365
int length = this . length ;
@@ -315,7 +378,9 @@ public bool TryCopyTo(Span<T> destination)
315
378
/// <inheritdoc cref="RefEnumerable{T}.ToArray"/>
316
379
public T [ ] ToArray ( )
317
380
{
318
- #if NETSTANDARD2_1_OR_GREATER
381
+ #if NET7_0_OR_GREATER
382
+ int length = this . length ;
383
+ #elif NETSTANDARD2_1_OR_GREATER
319
384
int length = this . span . Length ;
320
385
#else
321
386
int length = this . length ;
@@ -341,7 +406,9 @@ public T[] ToArray()
341
406
[ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
342
407
public static implicit operator ReadOnlyRefEnumerable < T > ( RefEnumerable < T > enumerable )
343
408
{
344
- #if NETSTANDARD2_1_OR_GREATER
409
+ #if NET7_0_OR_GREATER
410
+ return new ( in enumerable . Reference , enumerable . Length , enumerable . Step ) ;
411
+ #elif NETSTANDARD2_1_OR_GREATER
345
412
return new ( enumerable . Span , enumerable . Step ) ;
346
413
#else
347
414
return new ( enumerable . Instance , enumerable . Offset , enumerable . Length , enumerable . Step ) ;
@@ -353,7 +420,13 @@ public static implicit operator ReadOnlyRefEnumerable<T>(RefEnumerable<T> enumer
353
420
/// </summary>
354
421
public ref struct Enumerator
355
422
{
356
- #if NETSTANDARD2_1_OR_GREATER
423
+ #if NET7_0_OR_GREATER
424
+ /// <inheritdoc cref="ReadOnlyRefEnumerable{T}.reference"/>
425
+ private readonly ref readonly T reference ;
426
+
427
+ /// <inheritdoc cref="ReadOnlyRefEnumerable{T}.length"/>
428
+ private readonly int length ;
429
+ #elif NETSTANDARD2_1_OR_GREATER
357
430
/// <inheritdoc cref="ReadOnlyRefEnumerable{T}.span"/>
358
431
private readonly ReadOnlySpan < T > span ;
359
432
#else
@@ -375,7 +448,22 @@ public ref struct Enumerator
375
448
/// </summary>
376
449
private int position ;
377
450
378
- #if NETSTANDARD2_1_OR_GREATER
451
+ #if NET7_0_OR_GREATER
452
+ /// <summary>
453
+ /// Initializes a new instance of the <see cref="Enumerator"/> struct.
454
+ /// </summary>
455
+ /// <param name="reference">The <typeparamref name="T"/> reference to the first item of the sequence.</param>
456
+ /// <param name="length">The length of the sequence.</param>
457
+ /// <param name="step">The distance between items in the sequence to enumerate.</param>
458
+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
459
+ internal Enumerator ( in T reference , int length , int step )
460
+ {
461
+ this . reference = ref reference ;
462
+ this . length = length ;
463
+ this . step = step ;
464
+ this . position = - 1 ;
465
+ }
466
+ #elif NETSTANDARD2_1_OR_GREATER
379
467
/// <summary>
380
468
/// Initializes a new instance of the <see cref="Enumerator"/> struct.
381
469
/// </summary>
@@ -411,7 +499,9 @@ internal Enumerator(object? instance, IntPtr offset, int length, int step)
411
499
[ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
412
500
public bool MoveNext ( )
413
501
{
414
- #if NETSTANDARD2_1_OR_GREATER
502
+ #if NET7_0_OR_GREATER
503
+ return ++ this . position < this . length ;
504
+ #elif NETSTANDARD2_1_OR_GREATER
415
505
return ++ this . position < this . span . Length ;
416
506
#else
417
507
return ++ this . position < this . length ;
@@ -424,7 +514,9 @@ public readonly ref readonly T Current
424
514
[ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
425
515
get
426
516
{
427
- #if NETSTANDARD2_1_OR_GREATER
517
+ #if NET7_0_OR_GREATER
518
+ ref T r0 = ref Unsafe . AsRef ( in this . reference ) ;
519
+ #elif NETSTANDARD2_1_OR_GREATER
428
520
ref T r0 = ref this . span . DangerousGetReference ( ) ;
429
521
#else
430
522
ref T r0 = ref RuntimeHelpers . GetObjectDataAtOffsetOrPointerReference < T > ( this . instance , this . offset ) ;
0 commit comments