Span<T>.Enumerator Estrutura

Definição

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

public: value class Span<T>::Enumerator
public ref struct Span<T>.Enumerator
type Span<'T>.Enumerator = struct
Public Structure Span(Of T).Enumerator

Parâmetros de Tipo Genérico

T
Herança
Span<T>.Enumerator

Observações

O C# foreach da linguagem C# e o Para cada um... A construção seguinte em Visual Basic esconde a complexidade dos enumeradores. Em vez de manipular diretamente o enumerador, recomenda-se usar foreach ou For Each...Next

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

Current devolve o mesmo valor até MoveNext ser chamado. MoveNext define Current para o item seguinte no Span<T>.

Se MoveNext passar o fim do Span<T>, MoveNext devolve false. Quando o enumerador está neste estado, chamadas subsequentes também MoveNext retornam false e Current é indefinido. Não pode definir Current para o primeiro item do Span<T> novamente; deve criar uma nova instância de enumerador em vez disso.

O enumerador não tem acesso exclusivo ao Span<T>. Além disso, os dados subjacentes em que o span se baseia também podem ser modificados. Portanto, enumerar através de um intervalo não é intrinsecamente um procedimento seguro para threads. Para garantir a segurança das threads durante a enumeração, deve implementar a sua própria sincronização. Por exemplo, o código seguinte tem uma condição de corrida. Não garante que o intervalo será enumerado antes da execução do ClearContents método. Como resultado, o array subjacente é limpo durante a enumeração do intervalo:

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
module Program

open System
open System.Threading.Tasks

let array = Array.zeroCreate<byte> 5

let clearContents () =
    Task.Delay(20).Wait()
    lock array (fun () -> 
        Array.Clear(array, 0, array.Length) )

let enumerateSpan (span: Span<byte>) =
    for element in span do
        printfn $"{element}"
        Task.Delay(10).Wait()

[<EntryPoint>]
let main _ =
    Random(42).NextBytes array
    printfn "%A" array
    let span: Span<byte> = array

    Task.Run clearContents |> ignore

    enumerateSpan span
    
    0

// The example displays output like the following:
//     62
//     23
//     186
//     0
//     0

Se sincronizares o acesso ao array antes de enumerar o span, como a versão EnumerateSpan revista do método faz no exemplo seguinte, o ClearContents método não modifica os dados do span subjacentes durante a enumeração. Note-se que o exemplo bloqueia o array subjacente em que o span se baseia.

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
let enumerateSpan (span: Span<byte>) =
    // Spans cannot be accessed in closures including in the F# lock function.
    // Monitor.Enter and Monitor.Exit are used here directly.
    Monitor.Enter array
    try
        for element in span do
            printfn $"{element}"
            Task.Delay(10).Wait()
    finally
        Monitor.Exit array
// The example displays the following output:
//    62
//    23
//    186
//    150
//    174

Ao contrário de algumas outras estruturas enumeradoras em .NET, a Span<T>.Enumerator:

  • Não implementa a IEnumerator interface OU IEnumerator<T> . Isto porque Span<T>.Enumerator é um ref struct.

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

Propriedades

Name Description
Current

Recebe uma referência ao item na posição atual do recenseador.

Métodos

Name Description
MoveNext()

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

Aplica-se a