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

Определение

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

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

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<T> не реализует IEnumerator интерфейс. Это связано с Span<T>.Enumeratorструктурой ссылок.

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

Свойства

Имя Описание
Current

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

Методы

Имя Описание
MoveNext()

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

Явные реализации интерфейса

Имя Описание
IDisposable.Dispose()

Выполняет определяемые приложением задачи, связанные с освобождением, освобождением или сбросом неуправляемых ресурсов.

IEnumerator.Current

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

IEnumerator.Reset()

Задает перечислителю начальную позицию, которая перед первым элементом в коллекции.

IEnumerator<T>.Current

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

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