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
- Наследование
Комментарии
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>. |