Span<T>.Enumerator Estructura

Definición

Proporciona un enumerador para los elementos de .Span<T>

public: value class Span<T>::Enumerator : System::Collections::Generic::IEnumerator<T>
public: value class Span<T>::Enumerator
public ref struct Span<T>.Enumerator : System.Collections.Generic.IEnumerator<T>
public ref struct Span<T>.Enumerator
type Span<'T>.Enumerator = struct
    interface IEnumerator<'T>
    interface IEnumerator
    interface IDisposable
type Span<'T>.Enumerator = struct
Public Structure Span(Of T).Enumerator
Implements IEnumerator(Of T)
Public Structure Span(Of T).Enumerator

Parámetros de tipo

T
Herencia
Span<T>.Enumerator
Implementaciones

Comentarios

El foreach del lenguaje C# y el For Each... A continuación 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, Current no está definido. Debe llamar MoveNext a para avanzar 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 elemento siguiente 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 también devuelven MoveNextfalse 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, también se pueden modificar los datos subyacentes en los que se basa el intervalo. 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 hace la versión revisada del EnumerateSpan método 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, el Span<T>.Enumerator:

  • No implementa la IEnumerator interfaz o IEnumerator<T> . Esto se debe a Span<T>.Enumerator que 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

Nombre Description
Current

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

Métodos

Nombre Description
MoveNext()

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

Implementaciones de interfaz explícitas

Nombre Description
IDisposable.Dispose()

Realiza tareas definidas por la aplicación asociadas a la liberación, liberación o restablecimiento de recursos no administrados.

IEnumerator.Current

Obtiene el elemento de la colección en la posición actual del enumerador.

IEnumerator.Reset()

Establece el enumerador en su posición inicial, que es antes del primer elemento de la colección.

IEnumerator<T>.Current

Obtiene el elemento de la colección en la posición actual del enumerador.

Se aplica a