Span<T>.Enumerator Структура

Определение

Предоставляет перечислитель для элементов 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

Параметры типа

T
Наследование
Span<T>.Enumerator

Комментарии

C# foreach языка C# и For Each... Следующая конструкция в Visual Basic скрывает сложность перечислителей. Вместо прямого управления перечислителем рекомендуется использовать foreach или For Each...Next использовать его напрямую.

Изначально перечислитель размещается перед первым элементом в элементе Span<T>. В этой позиции значение свойства Current не определено. Перед чтением значения Currentнеобходимо вызвать MoveNext перечислитель к первому элементу.Span<T>

Current возвращает то же значение до MoveNext вызова. MoveNext задает Current для следующего элемента в элементе Span<T>.

Если MoveNext передает конец , Span<T>MoveNext возвращается false. Если перечислитель находится в этом состоянии, последующие вызовы MoveNext также возвращаются false и Current не определено. Нельзя задать Current первый элемент снова Span<T> . Вместо этого необходимо создать новый экземпляр перечислителя.

Перечислитель не имеет монопольного доступа к Span<T>. Кроме того, можно изменить базовые данные, на которых основан диапазон. Таким образом, перечисление через диапазон по сути не является потокобезопасной процедурой. Чтобы гарантировать безопасность потоков во время перечисления, необходимо реализовать собственную синхронизацию. Например, следующий код имеет состояние гонки. Он не гарантирует, что диапазон будет перечислен перед выполнением ClearContents метода. В результате базовый массив очищается во время перечисления диапазона:

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

Если вы синхронизируете доступ к массиву перед перечислением диапазона, так как измененная версия EnumerateSpan метода выполняется в следующем примере, ClearContents метод не изменяет базовые данные диапазона во время перечисления. Обратите внимание, что в примере блокируется базовый массив, на котором основан диапазон.

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

В отличие от некоторых других структур перечислителя в .NET, :Span<T>.Enumerator

  • Не реализует IEnumerator интерфейс или IEnumerator<T> интерфейс. Это связано с тем, что Span<T>.Enumerator это структура ссылок.

  • Не включает метод, который может задать перечислителю начальную Reset позицию перед первым элементом в диапазоне. (Метод IEnumerator.Reset() должен быть реализован как часть интерфейса, но большинство реализаций либо вызывают исключение, либо не предоставляют реализацию.)

Свойства

Current

Возвращает ссылку на элемент в текущей позиции перечислителя.

Методы

MoveNext()

Перемещает перечислитель к следующему элементу Span<T>.

Применяется к