Eu estava experimentando algumas coisas com o Span<T>
tipo. Meu objetivo era fazer um método de extensão para enumerar a divisão de a ReadOnlySpan<char>
, para ser usado da seguinte forma:
var x = "foo,bar,baz".AsSpan();
var options = StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries;
foreach (var word in x.EnumerateSplit(',', options))
{
// Should enumerate foo, bar and baz
}
Mas quando eu implemento meu próprio tipo de enumerador que encapsula uma Span<Range>.Enumerator
instância nos bastidores, um IndexOutOfRangeException
é lançado ao acessar a Current
propriedade do enumerador encapsulado.
Tentei criar o enumerador mais básico que tivesse apenas uma lógica de encapsulamento sem mecânica de divisão:
public ref struct BasicEnumerator
{
// Encapsulated enumerator
private readonly Span<Range>.Enumerator _enumerator;
public Range Current => _enumerator.Current;
public BasicEnumerator(Span<Range>.Enumerator enumerator)
{
_enumerator = enumerator;
}
public bool MoveNext() => _enumerator.MoveNext();
// Called by foreach
public BasicEnumerator GetEnumerator() => this;
}
Com esse BasicEnumerator
tipo, eu esperava pelo menos que esse trecho de código funcionasse:
Span<Range> test = stackalloc Range[5];
var enumerator = new BasicEnumerator(test.GetEnumerator());
foreach (Range r in enumerator)
{
Console.WriteLine(r);
}
Mas an IndexOutOfRangeException
é lançado na primeira iteração.
Eu também tentei mais simples sem usar foreach
:
Span<Range> test = stackalloc Range[5];
var enumerator = new BasicEnumerator(test.GetEnumerator());
if (enumerator.MoveNext())
{
Console.WriteLine(enumerator.Current);
}
O IndexOutOfRangeException
ainda é lançado ao tentar acessar o arquivo enumerator.Current
.
Observe que quando eu uso o Span<Range>.Enumerator
em vez disso (da mesma maneira), funciona:
Span<Range> test = stackalloc Range[5];
Span<Range>.Enumerator enumerator = test.GetEnumerator();
if (enumerator.MoveNext())
{
Console.WriteLine(enumerator.Current);
}
Durante a depuração, descobri que não está funcionando porque o Span<Range>.Enumerator.MoveNext
método não aumenta o índice subjacente, mas ainda retorna true
:
Captura de tela de depuração do Visual Studio
Eu realmente não sei por que está fazendo isso. Eu diria que é um problema de referência, mas não sei por que e como resolvê-lo. Tentei encontrar documentação sobre um caso de uso semelhante, sem sucesso.
Estou usando o .NET 8.