Span<T>.Enumerator Struktura

Definicja

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

Parametry typu

T
Dziedziczenie
Span<T>.Enumerator
Implementuje

Uwagi

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

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

Current zwraca tę samą wartość do MoveNext momentu wywołania. MoveNext ustawia Current wartość na następny element w elemencie Span<T>.

Jeśli MoveNext element przejdzie na końcu Span<T>elementu , MoveNext zwraca wartość false. Gdy moduł wyliczający jest w tym stanie, kolejne wywołania MoveNext również zwracają false i Current są niezdefiniowane. Nie można ustawić Current na pierwszy element ponownie Span<T> . Należy zamiast tego utworzyć nowe wystąpienie modułu wyliczającego.

Moduł wyliczający nie ma wyłącznego dostępu do elementu Span<T>. Ponadto można modyfikować bazowe dane, na których opiera się zakres. 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, ż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 zsynchronizujesz dostęp do tablicy przed wyliczeniem zakresu, ponieważ zmieniona wersja EnumerateSpan metody w poniższym przykładzie ClearContents nie modyfikuje bazowych danych zakresu 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 innych struktur modułu wyliczającego w .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 swoją pozycję początkową przed pierwszym elementem w zakresie. (Metoda IEnumerator.Reset() musi być zaimplementowana jako część interfejsu, ale większość implementatorów zgłasza wyjątek lub nie zapewnia implementacji).

Właściwości

Nazwa Opis
Current

Pobiera odwołanie do elementu w bieżącym położeniu modułu wyliczającego.

Metody

Nazwa Opis
MoveNext()

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

Jawne implementacje interfejsu

Nazwa Opis
IDisposable.Dispose()

Wykonuje zadania zdefiniowane przez aplikację skojarzone z zwalnianiem, wydawaniem lub resetowaniem niezarządzanych zasobów.

IEnumerator.Current

Pobiera element w kolekcji na bieżącej pozycji modułu wyliczającego.

IEnumerator.Reset()

Ustawia moduł wyliczający na swoją początkową pozycję, która znajduje się przed pierwszym elementem w kolekcji.

IEnumerator<T>.Current

Pobiera element w kolekcji na bieżącej pozycji modułu wyliczającego.

Dotyczy