@@ -21,7 +21,17 @@ namespace CommunityToolkit.HighPerformance.Enumerables;
2121/// <typeparam name="T">The type of items to enumerate.</typeparam>
2222public readonly ref struct ReadOnlyRefEnumerable < T >
2323{
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
2535 /// <summary>
2636 /// The <see cref="ReadOnlySpan{T}"/> instance pointing to the first item in the target memory area.
2737 /// </summary>
@@ -51,6 +61,7 @@ public readonly ref struct ReadOnlyRefEnumerable<T>
5161 private readonly int step ;
5262
5363#if NETSTANDARD2_1_OR_GREATER
64+ #if ! NET7_0_OR_GREATER
5465 /// <summary>
5566 /// Initializes a new instance of the <see cref="ReadOnlyRefEnumerable{T}"/> struct.
5667 /// </summary>
@@ -59,9 +70,15 @@ public readonly ref struct ReadOnlyRefEnumerable<T>
5970 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
6071 private ReadOnlyRefEnumerable ( ReadOnlySpan < T > span , int step )
6172 {
73+ #if NET7_0_OR_GREATER
74+ this . reference = ref MemoryMarshal . GetReference ( span ) ;
75+ this . length = span . Length ;
76+ #else
6277 this . span = span ;
78+ #endif
6379 this . step = step ;
6480 }
81+ #endif
6582
6683 /// <summary>
6784 /// Initializes a new instance of the <see cref="ReadOnlyRefEnumerable{T}"/> struct.
@@ -72,8 +89,14 @@ private ReadOnlyRefEnumerable(ReadOnlySpan<T> span, int step)
7289 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
7390 internal ReadOnlyRefEnumerable ( in T reference , int length , int step )
7491 {
92+ #if NET7_0_OR_GREATER
93+ this . reference = ref reference ;
94+ this . length = length ;
95+ this . step = step ;
96+ #else
7597 this . span = MemoryMarshal . CreateReadOnlySpan ( ref Unsafe . AsRef ( reference ) , length ) ;
7698 this . step = step ;
99+ #endif
77100 }
78101
79102 /// <summary>
@@ -124,7 +147,9 @@ internal ReadOnlyRefEnumerable(object? instance, IntPtr offset, int length, int
124147 public int Length
125148 {
126149 [ 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
128153 get => this . span . Length ;
129154#else
130155 get => this . length ;
@@ -149,7 +174,9 @@ public ref readonly T this[int index]
149174 ThrowHelper . ThrowIndexOutOfRangeException ( ) ;
150175 }
151176
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
153180 ref T r0 = ref MemoryMarshal . GetReference ( this . span ) ;
154181#else
155182 ref T r0 = ref RuntimeHelpers . GetObjectDataAtOffsetOrPointerReference < T > ( this . instance , this . offset ) ;
@@ -181,7 +208,9 @@ public ref readonly T this[Index index]
181208 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
182209 public Enumerator GetEnumerator ( )
183210 {
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
185214 return new ( this . span , this . step ) ;
186215#else
187216 return new ( this . instance , this . offset , this . length , this . step ) ;
@@ -197,7 +226,26 @@ public Enumerator GetEnumerator()
197226 /// </exception>
198227 public void CopyTo ( RefEnumerable < T > destination )
199228 {
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
201249 if ( this . step == 1 )
202250 {
203251 destination . CopyFrom ( this . span ) ;
@@ -238,7 +286,10 @@ public void CopyTo(RefEnumerable<T> destination)
238286 /// <returns>Whether or not the operation was successful.</returns>
239287 public bool TryCopyTo ( RefEnumerable < T > destination )
240288 {
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
242293 int sourceLength = this . span . Length ;
243294 int destinationLength = destination . Span . Length ;
244295#else
@@ -265,7 +316,17 @@ public bool TryCopyTo(RefEnumerable<T> destination)
265316 /// </exception>
266317 public void CopyTo ( Span < T > destination )
267318 {
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
269330 if ( this . step == 1 )
270331 {
271332 this . span . CopyTo ( destination ) ;
@@ -296,7 +357,9 @@ public void CopyTo(Span<T> destination)
296357 /// <returns>Whether or not the operation was successful.</returns>
297358 public bool TryCopyTo ( Span < T > destination )
298359 {
299- #if NETSTANDARD2_1_OR_GREATER
360+ #if NET7_0_OR_GREATER
361+ int length = this . length ;
362+ #elif NETSTANDARD2_1_OR_GREATER
300363 int length = this . span . Length ;
301364#else
302365 int length = this . length ;
@@ -315,7 +378,9 @@ public bool TryCopyTo(Span<T> destination)
315378 /// <inheritdoc cref="RefEnumerable{T}.ToArray"/>
316379 public T [ ] ToArray ( )
317380 {
318- #if NETSTANDARD2_1_OR_GREATER
381+ #if NET7_0_OR_GREATER
382+ int length = this . length ;
383+ #elif NETSTANDARD2_1_OR_GREATER
319384 int length = this . span . Length ;
320385#else
321386 int length = this . length ;
@@ -341,7 +406,9 @@ public T[] ToArray()
341406 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
342407 public static implicit operator ReadOnlyRefEnumerable < T > ( RefEnumerable < T > enumerable )
343408 {
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
345412 return new ( enumerable . Span , enumerable . Step ) ;
346413#else
347414 return new ( enumerable . Instance , enumerable . Offset , enumerable . Length , enumerable . Step ) ;
@@ -353,7 +420,13 @@ public static implicit operator ReadOnlyRefEnumerable<T>(RefEnumerable<T> enumer
353420 /// </summary>
354421 public ref struct Enumerator
355422 {
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
357430 /// <inheritdoc cref="ReadOnlyRefEnumerable{T}.span"/>
358431 private readonly ReadOnlySpan < T > span ;
359432#else
@@ -375,7 +448,22 @@ public ref struct Enumerator
375448 /// </summary>
376449 private int position ;
377450
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
379467 /// <summary>
380468 /// Initializes a new instance of the <see cref="Enumerator"/> struct.
381469 /// </summary>
@@ -411,7 +499,9 @@ internal Enumerator(object? instance, IntPtr offset, int length, int step)
411499 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
412500 public bool MoveNext ( )
413501 {
414- #if NETSTANDARD2_1_OR_GREATER
502+ #if NET7_0_OR_GREATER
503+ return ++ this . position < this . length ;
504+ #elif NETSTANDARD2_1_OR_GREATER
415505 return ++ this . position < this . span . Length ;
416506#else
417507 return ++ this . position < this . length ;
@@ -424,7 +514,9 @@ public readonly ref readonly T Current
424514 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
425515 get
426516 {
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
428520 ref T r0 = ref this . span . DangerousGetReference ( ) ;
429521#else
430522 ref T r0 = ref RuntimeHelpers . GetObjectDataAtOffsetOrPointerReference < T > ( this . instance , this . offset ) ;
0 commit comments