Ler em inglês

Compartilhar via


Span<T>.Enumerator Estrutura

Definição

Fornece um enumerador para os elementos de um Span<T>.

C#
public ref struct Span<T>.Enumerator

Parâmetros de tipo

T
Herança
Span<T>.Enumerator

Comentários

O foreach do C# da linguagem C# e o for each... O próximo constructo no Visual Basic oculta a complexidade dos enumeradores. Em vez de manipular diretamente o enumerador, é recomendável usar foreach ou For Each...Next .

Inicialmente, o enumerador é posicionado antes do primeiro elemento no Span<T>. Nesta posição, Current está indefinido. Você deve chamar MoveNext para avançar o enumerador para o primeiro item no Span<T> antes de ler o valor de Current.

Current retorna o mesmo valor até MoveNext que seja chamado. MoveNext define Current como o próximo item no Span<T>.

Se MoveNext passar o final do Span<T>, MoveNext retornará false. Quando o enumerador está nesse estado, as chamadas subsequentes para MoveNext também retornam false e Current são indefinidas. Não é possível definir Current como o primeiro item no Span<T> novamente; em vez disso, você deve criar uma nova instância de enumerador.

O enumerador não tem acesso exclusivo ao Span<T>. Além disso, os dados subjacentes nos quais o intervalo se baseia também podem ser modificados. Portanto, enumerar por meio de um intervalo não é intrinsecamente um procedimento thread-safe. Para garantir a segurança do thread durante a enumeração, você deve implementar sua própria sincronização. Por exemplo, o código a seguir tem uma condição de corrida. Ele não garante que o intervalo será enumerado antes da execução do ClearContents método. Como resultado, a matriz subjacente é limpa durante a enumeração do intervalo:

C#
using System;
using System.Threading.Tasks;

class Program
{
    private static readonly byte[] _array = new byte[5];

    static void Main()
    {
        new Random(42).NextBytes(_array);
        Span<byte> span = _array;

        Task.Run( () => ClearContents() );

       EnumerateSpan(span);
    }

    public static void ClearContents()
    {
        Task.Delay(20).Wait();
        lock (_array)
        {
           Array.Clear(_array, 0, _array.Length);
        }
    }

    public static void EnumerateSpan(Span<byte> span)
    {
        foreach (byte element in span)
        {
            Console.WriteLine(element);
            Task.Delay(10).Wait();
        }
    }
}
// The example displays output like the following:
//     62
//     23
//     186
//     0
//     0

Se você sincronizar o acesso à matriz antes de enumerar o intervalo, como a versão revisada do EnumerateSpan método faz no exemplo a seguir, o ClearContents método não modifica os dados de span subjacentes durante a enumeração. Observe que o exemplo bloqueia a matriz subjacente na qual o intervalo se baseia.

C#
public static void EnumerateSpan(Span<byte> span)
{
    lock (_array)
    {
        foreach (byte element in span)
        {
            Console.WriteLine(element);
            Task.Delay(10).Wait();
        }
    }
}
// The example displays the following output:
//    62
//    23
//    186
//    150
//    174

Ao contrário de algumas outras estruturas de enumerador no .NET, o Span<T>.Enumerator:

  • Não implementa a IEnumerator interface ou IEnumerator<T> . Isso ocorre porque Span<T>.Enumerator é um struct ref.

  • Não inclui um Reset método , que pode definir o enumerador como sua posição inicial antes do primeiro elemento no intervalo. (O IEnumerator.Reset() método deve ser implementado como parte da interface, mas a maioria dos implementadores gera uma exceção ou não fornece nenhuma implementação.)

Propriedades

Current

Obtém uma referência ao item na posição atual do enumerador.

Métodos

MoveNext()

Avança o enumerador para o próximo item do Span<T>.

Aplica-se a

Produto Versões
.NET Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9, 10
.NET Standard 2.0 (package-provided), 2.1