Sdílet prostřednictvím


Span<T>.Enumerator Struktura

Definice

Poskytuje enumerátor pro prvky objektu 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
Dědičnost
Span<T>.Enumerator

Poznámky

Foreach jazyka C# a For Each... Další konstruktor v jazyce Visual Basic skryje složitost enumerátorů. Místo přímé manipulace s enumerátorem se doporučuje použít nebo foreachFor Each...Next .

Zpočátku je enumerátor umístěn před prvním prvkem v objektu Span<T>. Na této pozici Current není definován. Před čtením hodnoty Currentje nutné volatMoveNext, aby se enumerátor přepojí na první položku v objektu Span<T> .

Current vrátí stejnou hodnotu, dokud MoveNext není volána. MoveNext nastaví Current na další položku v objektu Span<T>.

Pokud MoveNext projde konec parametru Span<T>, MoveNext vrátí falsehodnotu . Pokud je enumerátor v tomto stavu, vrátí false se MoveNext také další volání a Current není definováno. Nelze nastavit Current na první položku znovu; Span<T> místo toho musíte vytvořit novou instanci enumerátoru.

Enumerátor nemá výhradní přístup k objektu Span<T>. Kromě toho je možné upravit také podkladová data, na kterých je rozsah založen. Proto výčet přes rozpětí není vnitřně bezpečný postup pro přístup z více vláken. Abyste zajistili bezpečnost vláken během výčtu, musíte implementovat vlastní synchronizaci. Například následující kód má podmínku časování. Nezajistí, že span bude výčet před spuštěním ClearContents metody. V důsledku toho se podkladové pole během výčtu rozsahu vymaže:

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

Pokud synchronizujete přístup k poli před výčtem rozsahu, jak to dělá revidovaná verze EnumerateSpan metody v následujícím příkladu ClearContents , metoda během výčtu neupravuje podkladová data spanu. Všimněte si, že příklad uzamkne podkladové pole, na kterém je rozsah založen.

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

Na rozdíl od některých jiných struktur enumerátoru v .NET:Span<T>.Enumerator

  • Neimplementuje IEnumerator rozhraní nebo IEnumerator<T> . Je to proto, že Span<T>.Enumerator se jedná o referenční strukturu.

  • Nezahrnuje metodu Reset , která může nastavit enumerátor na počáteční pozici před prvním prvkem v rozsahu. (Metoda IEnumerator.Reset() musí být implementována jako součást rozhraní, ale většina implementátorů buď vyvolá výjimku, nebo neposkytuje žádnou implementaci.)

Vlastnosti

Current

Získá odkaz na položku na aktuální pozici enumerátoru.

Metody

MoveNext()

Posune enumerátor na další položku objektu Span<T>.

Platí pro