Partager via


Span<T>.Enumerator Structure

Définition

Fournit un énumérateur pour les éléments d’un 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

Paramètres de type

T
Héritage
Span<T>.Enumerator

Remarques

Foreach C# du langage C# et For Each... La construction suivante dans Visual Basic masque la complexité des énumérateurs. Au lieu de manipuler directement l’énumérateur, l’utilisation foreach ou For Each...Next l’utilisation est recommandée.

Initialement, l’énumérateur est positionné avant le premier élément du Span<T>. À cette position, Current n'est pas défini. Vous devez appeler MoveNext pour faire avancer l’énumérateur vers le premier élément de l’avant Span<T> de lire la valeur de Current.

Current retourne la même valeur jusqu’à ce qu’elle MoveNext soit appelée. MoveNext définit Current l’élément suivant dans le Span<T>.

Si MoveNext elle passe la fin de l’objet Span<T>, MoveNext retourne false. Lorsque l’énumérateur se trouve à cet état, les appels suivants à MoveNext retourner false et Current ne sont pas définis. Vous ne pouvez pas définir Current le premier élément à nouveau ; vous devez créer une instance d’énumérateur à la Span<T> place.

L’énumérateur n’a pas d’accès exclusif au Span<T>. En outre, les données sous-jacentes sur lesquelles l’étendue est basée peuvent également être modifiées. Par conséquent, l’énumération à travers une étendue n’est intrinsèquement pas une procédure thread-safe. Pour garantir la sécurité des threads pendant l’énumération, vous devez implémenter votre propre synchronisation. Par exemple, le code suivant a une condition de concurrence. Elle ne garantit pas que l’étendue sera énumérée avant l’exécution de la ClearContents méthode. Par conséquent, le tableau sous-jacent est effacé pendant l’énumération de l’étendue :

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

Si vous synchronisez l’accès au tableau avant d’énumérer l’étendue, comme le fait la version révisée de la méthode dans l’exemple suivant, la ClearContents méthode ne modifie pas les données d’étendue sous-jacentes pendant l’énumérationEnumerateSpan. Notez que l’exemple verrouille le tableau sous-jacent sur lequel l’étendue est basée.

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

Contrairement à d’autres structures d’énumérateur dans .NET, les Span<T>.Enumeratoréléments suivants :

  • N’implémente pas l’interface ou IEnumerator<T> l’interfaceIEnumerator. En effet Span<T>.Enumerator , il s’agit d’un struct ref.

  • N’inclut pas de Reset méthode, qui peut définir l’énumérateur sur sa position initiale avant le premier élément de l’étendue. (La IEnumerator.Reset() méthode doit être implémentée dans le cadre de l’interface, mais la plupart des implémenteurs lèvent une exception ou ne fournissent aucune implémentation.)

Propriétés

Current

Obtient une référence à l’élément à la position actuelle de l’énumérateur.

Méthodes

MoveNext()

Avance l’énumérateur à l’élément suivant de Span<T>.

S’applique à