Span<T>.Enumerator Struct

Definizione

Fornisce un enumeratore per gli elementi di un oggetto 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

Parametri di tipo

T
Ereditarietà
Span<T>.Enumerator
Implementazioni

Commenti

C# foreach del linguaggio C# e For Each... Successivamente costrutto in Visual Basic nasconde la complessità degli enumeratori. Anziché modificare direttamente l'enumeratore, è consigliabile usare foreach o For Each...Next .

Inizialmente, l'enumeratore viene posizionato prima del primo elemento dell'oggetto Span<T>. In questa posizione, Current non è definito. È necessario chiamare per far avanzare MoveNext l'enumeratore al primo elemento di Span<T> prima di leggere il valore di Current.

Current restituisce lo stesso valore fino a quando MoveNext non viene chiamato . MoveNext imposta Current sull'elemento successivo nell'oggetto Span<T>.

Se MoveNext passa la fine di Span<T>, MoveNext restituisce false. Quando l'enumeratore è in questo stato, anche le chiamate successive a MoveNext restituiscono false e Current non sono predefinite. Non è possibile impostare Current nuovamente il primo elemento. È invece necessario creare una nuova istanza dell'enumeratore Span<T> .

L'enumeratore non ha accesso esclusivo all'oggetto Span<T>. Inoltre, è possibile modificare anche i dati sottostanti su cui si basa l'intervallo. Pertanto, l'enumerazione tramite un intervallo non è intrinsecamente una procedura thread-safe. Per garantire la thread safety durante l'enumerazione, è necessario implementare la sincronizzazione personalizzata. Ad esempio, il codice seguente ha una race condition. Non garantisce che l'intervallo venga enumerato prima dell'esecuzione del ClearContents metodo. Di conseguenza, la matrice sottostante viene cancellata durante l'enumerazione dell'intervallo:

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 si sincronizza l'accesso alla matrice prima di enumerare l'intervallo, come la versione modificata del EnumerateSpan metodo nell'esempio seguente, il ClearContents metodo non modifica i dati dell'intervallo sottostante durante l'enumerazione. Si noti che l'esempio blocca la matrice sottostante su cui si basa l'intervallo.

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 differenza di altre strutture dell'enumeratore in .NET, il Span<T>.Enumerator:

  • Non implementa l'interfaccia IEnumerator o IEnumerator<T> . Questo perché Span<T>.Enumerator è uno struct di riferimento.

  • Non include un Reset metodo che può impostare l'enumeratore sulla posizione iniziale prima del primo elemento nell'intervallo. Il IEnumerator.Reset() metodo deve essere implementato come parte dell'interfaccia, ma la maggior parte degli implementatori genera un'eccezione o non fornisce alcuna implementazione.

Proprietà

Nome Descrizione
Current

Ottiene un riferimento all'elemento nella posizione corrente dell'enumeratore.

Metodi

Nome Descrizione
MoveNext()

Sposta l'enumeratore all'elemento successivo di Span<T>.

Implementazioni dell'interfaccia esplicita

Nome Descrizione
IDisposable.Dispose()

Esegue attività definite dall'applicazione associate alla liberazione, al rilascio o alla reimpostazione di risorse non gestite.

IEnumerator.Current

Ottiene l'elemento nella raccolta in corrispondenza della posizione corrente dell'enumeratore.

IEnumerator.Reset()

Imposta l'enumeratore sulla posizione iniziale, ovvero prima del primo elemento della raccolta.

IEnumerator<T>.Current

Ottiene l'elemento nella raccolta in corrispondenza della posizione corrente dell'enumeratore.

Si applica a