Last active
January 6, 2020 00:19
-
-
Save Sergio0694/3eff2b8415393b008d0fd595b69e8f62 to your computer and use it in GitHub Desktop.
A fast and allocation-free method to enumerate items in a collection
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
using System.Runtime.CompilerServices; | |
using System.Runtime.InteropServices; | |
namespace System | |
{ | |
/// <summary> | |
/// A <see langword="ref"/> <see langword="struct"/> that enumerates the items in a given <see cref="ReadOnlySpan{T}"/> instance | |
/// </summary> | |
/// <typeparam name="T">The type of items to enumerate</typeparam> | |
public readonly ref struct ReadOnlySpanEnumerator<T> | |
{ | |
/// <summary> | |
/// The source <see cref="ReadOnlySpan{T}"/> instance | |
/// </summary> | |
private readonly ReadOnlySpan<T> Span; | |
/// <summary> | |
/// Creates a new <see cref="ReadOnlySpanEnumerator{T}"/> instance with the specified parameters | |
/// </summary> | |
/// <param name="span">The source <see cref="ReadOnlySpan{T}"/> to enumerate</param> | |
public ReadOnlySpanEnumerator(ReadOnlySpan<T> span) | |
{ | |
Span = span; | |
} | |
/// <inheritdoc cref="IEnumerable{T}.GetEnumerator"/> | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |
public Enumerator GetEnumerator() => new Enumerator(Span); | |
/// <summary> | |
/// An enumerator for a source <see cref="ReadOnlySpan{T}"/> instance | |
/// </summary> | |
public ref struct Enumerator | |
{ | |
/// <summary> | |
/// The target <see cref="ReadOnlySpan{T}"/> instance | |
/// </summary> | |
private readonly ReadOnlySpan<T> Span; | |
/// <summary> | |
/// The current index | |
/// </summary> | |
private int _Index; | |
/// <summary> | |
/// Creates a new <see cref="Enumerator"/> instance with the specified parameters | |
/// </summary> | |
/// <param name="span">The source <see cref="ReadOnlySpan{T}"/> instance</param> | |
public Enumerator(ReadOnlySpan<T> span) | |
{ | |
Span = span; | |
_Index = -1; | |
} | |
/// <inheritdoc cref="System.Collections.IEnumerator.MoveNext"/> | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |
public bool MoveNext() | |
{ | |
int index = _Index + 1; | |
if (index < Span.Length) | |
{ | |
_Index = index; | |
return true; | |
} | |
return false; | |
} | |
/// <inheritdoc cref="IEnumerator{T}.Current"/> | |
public (int Index, T Value) Current | |
{ | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |
get | |
{ | |
int index = _Index; | |
T value = Unsafe.Add(ref MemoryMarshal.GetReference(Span), index); | |
return (index, value); | |
} | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Diagnostics.Contracts; | |
using System.Runtime.CompilerServices; | |
namespace System | |
{ | |
/// <summary> | |
/// A <see langword="class"/> with some extension methods for the <see cref="string"/> type | |
/// </summary> | |
public static class StringExtensions | |
{ | |
/// <summary> | |
/// Creates a new <see cref="ReadOnlySpanEnumerator{T}"/> instance with the specified parameters | |
/// </summary> | |
/// <param name="text">The source text to enumerate</param> | |
/// <returns>A <see cref="ReadOnlySpanEnumerator{T}"/> instance working on <paramref name="text"/></returns> | |
[Pure] | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |
public static ReadOnlySpanEnumerator<char> Enumerate(this string text) => new ReadOnlySpanEnumerator<char>(text.AsSpan()); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment