Span<T>.Enumerator Struktur

Definition

Stellt einen Enumerator für diese Elemente eines Span<T>-Elements bereit.

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

Typparameter

T
Vererbung
Span<T>.Enumerator

Hinweise

Der C# -Foreach der Sprache C# und der For Each... Das nächste Konstrukt in Visual Basic blendet die Komplexität von Enumeratoren aus. Anstatt den Enumerator direkt zu bearbeiten, wird die Verwendung von foreach oder For Each...Next empfohlen.

Zunächst wird der Enumerator vor dem ersten Element im Span<T>positioniert. An dieser Position ist Current nicht definiert. Sie müssen aufrufen MoveNext , um den Enumerator zum ersten Element in der zu wechseln, Span<T> bevor Sie den Wert von Currentlesen.

Current gibt den gleichen Wert zurück, bis MoveNext aufgerufen wird. MoveNextwird auf das nächste Element im Span<T>festgelegtCurrent.

Wenn MoveNext das Ende von Span<T>übergibt, MoveNext gibt zurück false. Wenn sich der Enumerator in diesem Zustand befindet, werden nachfolgende Aufrufe von MoveNext ebenfalls zurückgegeben false und Current sind nicht definiert. Sie können nicht auf das erste Element im Span<T> erneut festlegenCurrent. Stattdessen müssen Sie eine neue Enumeratorinstanz erstellen.

Der Enumerator hat keinen exklusiven Zugriff auf .Span<T> Darüber hinaus können die zugrunde liegenden Daten, auf denen die Spanne basiert, auch geändert werden. Daher ist das Aufzählen durch eine Spanne intrinsisch kein threadsicheres Verfahren. Um die Threadsicherheit während der Enumeration zu gewährleisten, müssen Sie eine eigene Synchronisierung implementieren. Der folgende Code weist beispielsweise eine Racebedingung auf. Es wird nicht sichergestellt, dass die Spanne aufgelistet wird, bevor die ClearContents Methode ausgeführt wird. Daher wird das zugrunde liegende Array während der Enumeration der Spanne gelöscht:

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

Wenn Sie den Zugriff auf das Array vor dem Aufzählen der Spanne synchronisieren, wie dies in der überarbeiteten Version der EnumerateSpan Methode im folgenden Beispiel der Fall ist, ändert die Methode während der ClearContents Enumeration keine zugrunde liegenden span-Daten. Beachten Sie, dass im Beispiel das zugrunde liegende Array gesperrt wird, auf dem die Spanne basiert.

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

Im Gegensatz zu einigen anderen Enumeratorstrukturen in .NET ist :Span<T>.Enumerator

  • Implementiert die IEnumerator -Schnittstelle oder IEnumerator<T> nicht. Dies liegt daran, dass Span<T>.Enumerator eine Verweisstruktur ist.

  • Enthält Reset keine -Methode, die den Enumerator auf seine Anfangsposition vor dem ersten Element in der Spanne festlegen kann. (Die IEnumerator.Reset() -Methode muss als Teil der -Schnittstelle implementiert werden, aber die meisten Implementierer lösen entweder eine Ausnahme aus oder stellen keine Implementierung bereit.)

Eigenschaften

Current

Ruft einen Verweis auf das Element an der aktuellen Position des Enumerators ab.

Methoden

MoveNext()

Legt den Enumerator auf das nächste Element von Span<T> fest.

Gilt für: