Span<T>.Enumerator Estructura

Definición

Proporciona un enumerador para los elementos de 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

T
Herencia
Span<T>.Enumerator

Comentarios

Foreach de C# del lenguaje C# y for Each... La siguiente construcción en Visual Basic oculta la complejidad de los enumeradores. En lugar de manipular directamente el enumerador, se recomienda usar foreach o For Each...Next .

Inicialmente, el enumerador se coloca antes del primer elemento de Span<T>. En esta posición, el valor de propiedad Current está sin definir. Debe llamar a para avanzar MoveNext el enumerador al primer elemento de Span<T> antes de leer el valor de Current.

Current devuelve el mismo valor hasta MoveNext que se llama a . MoveNextestablece Current en el siguiente elemento de .Span<T>

Si MoveNext pasa el final de Span<T>, MoveNext devuelve false. Cuando el enumerador está en este estado, las llamadas posteriores a MoveNext también devuelven false y Current no están definidas. No se puede establecer Current en el primer elemento de nuevo Span<T> ; en su lugar, debe crear una nueva instancia del enumerador.

El enumerador no tiene acceso exclusivo a Span<T>. Además, los datos subyacentes en los que se basa el intervalo también se pueden modificar. Por lo tanto, la enumeración a través de un intervalo no es intrínsecamente un procedimiento seguro para subprocesos. Para garantizar la seguridad de los subprocesos durante la enumeración, debe implementar su propia sincronización. Por ejemplo, el código siguiente tiene una condición de carrera. No garantiza que el intervalo se enumerará antes de que se ejecute el ClearContents método . Como resultado, la matriz subyacente se borra durante la enumeración del 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

Si sincroniza el acceso a la matriz antes de enumerar el intervalo, como la versión revisada del EnumerateSpan método lo hace en el ejemplo siguiente, el ClearContents método no modifica los datos de intervalo subyacentes durante la enumeración. Tenga en cuenta que el ejemplo bloquea la matriz subyacente en la que se basa el intervalo.

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

A diferencia de otras estructuras de enumerador en .NET, :Span<T>.Enumerator

  • No implementa la IEnumerator interfaz o IEnumerator<T> . Esto se debe a que Span<T>.Enumerator es una estructura ref.

  • No incluye un Reset método , que puede establecer el enumerador en su posición inicial antes del primer elemento del intervalo. (El IEnumerator.Reset() método debe implementarse como parte de la interfaz, pero la mayoría de los implementadores inician una excepción o no proporcionan ninguna implementación).

Propiedades

Current

Obtiene una referencia al elemento en la posición actual del enumerador.

Métodos

MoveNext()

Desplaza el enumerador al siguiente elemento de Span<T>.

Se aplica a