Span<T>.Enumerator Struktura

Definicja

Udostępnia moduł wyliczający dla elementów elementu 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

Parametry typu

T
Dziedziczenie
Span<T>.Enumerator

Uwagi

Foreach języka C# języka C# i dla każdego... Następna konstrukcja w Visual Basic ukrywa złożoność modułów wyliczania. Zamiast bezpośrednio manipulować modułem wyliczającym, zaleca się użycie foreach lub For Each...Next zalecane.

Początkowo moduł wyliczający jest umieszczony przed pierwszym elementem w elemecie Span<T>. Na tym stanowisku Current jest niezdefiniowany. Musisz wywołać metodę MoveNext , aby przejść do pierwszego elementu w elemencie Span<T> przed odczytaniem wartości Current.

Current zwraca tę samą wartość, dopóki MoveNext nie zostanie wywołana. MoveNext ustawia Current wartość na następny element w elemencie Span<T>.

Jeśli MoveNext przejdzie koniec elementu Span<T>, MoveNext zwraca wartość false. Gdy moduł wyliczający znajduje się w tym stanie, kolejne wywołania do MoveNext zwrócenia false i Current są niezdefiniowane. Nie można ustawić Current pierwszego elementu na Span<T> ponownie. Zamiast tego należy utworzyć nowe wystąpienie modułu wyliczającego.

Moduł wyliczający nie ma wyłącznego dostępu do elementu Span<T>. Ponadto bazowe dane, na których opiera się zakres, można również modyfikować. W związku z tym wyliczanie przez zakres nie jest wewnętrznie procedurą bezpieczną wątkowo. Aby zagwarantować bezpieczeństwo wątków podczas wyliczania, należy zaimplementować własną synchronizację. Na przykład poniższy kod ma warunek wyścigu. Nie gwarantuje ona, że zakres zostanie wyliczony przed wykonaniem ClearContents metody. W rezultacie macierz bazowa jest czyszczone podczas wyliczania zakresu:

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

Jeśli zsynchronizuj dostęp do tablicy przed wyliczeniem zakresu, ponieważ poprawiona wersja EnumerateSpan metody ma zastosowanie w poniższym przykładzie, ClearContents metoda nie modyfikuje danych zakresu bazowego podczas wyliczania. Należy pamiętać, że przykład blokuje macierz bazową, na której opiera się zakres.

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

W przeciwieństwie do niektórych innych struktur wyliczania na platformie .NET:Span<T>.Enumerator

  • Nie implementuje interfejsu IEnumerator lub IEnumerator<T> . Jest to spowodowane tym, że Span<T>.Enumerator jest strukturą ref.

  • Nie zawiera Reset metody, która może ustawić moduł wyliczający na jego pozycję początkową przed pierwszym elementem w zakresie. (Metoda IEnumerator.Reset() musi być zaimplementowana w ramach interfejsu, ale większość implementatorów zgłasza wyjątek lub nie zapewnia implementacji).

Właściwości

Current

Pobiera odwołanie do elementu w bieżącej pozycji modułu wyliczającego.

Metody

MoveNext()

Rozwija moduł wyliczający do następnego elementu .Span<T>

Dotyczy