Span<T>.Enumerator Estructura
Definición
Importante
Parte de la información hace referencia a la versión preliminar del producto, que puede haberse modificado sustancialmente antes de lanzar la versión definitiva. Microsoft no otorga ninguna garantía, explícita o implícita, con respecto a la información proporcionada aquí.
Proporciona un enumerador para los elementos de 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
Parámetros de tipo
- T
- Herencia
Comentarios
Foreach de C# del lenguaje C# y for Each... La siguiente construcción en Visual Basic oculta la complejidad de los enumeradores. En lugar de manipular directamente el enumerador, se recomienda usar foreach
o For Each...Next
.
Inicialmente, el enumerador se coloca antes del primer elemento de Span<T>. En esta posición, el valor de propiedad Current está sin definir. Debe llamar a para avanzar MoveNext el enumerador al primer elemento de Span<T> antes de leer el valor de Current.
Current devuelve el mismo valor hasta MoveNext que se llama a . MoveNextestablece Current en el siguiente elemento de .Span<T>
Si MoveNext pasa el final de Span<T>, MoveNext devuelve false
. Cuando el enumerador está en este estado, las llamadas posteriores a MoveNext también devuelven false
y Current no están definidas. No se puede establecer Current en el primer elemento de nuevo Span<T> ; en su lugar, debe crear una nueva instancia del enumerador.
El enumerador no tiene acceso exclusivo a Span<T>. Además, los datos subyacentes en los que se basa el intervalo también se pueden modificar. Por lo tanto, la enumeración a través de un intervalo no es intrínsecamente un procedimiento seguro para subprocesos. Para garantizar la seguridad de los subprocesos durante la enumeración, debe implementar su propia sincronización. Por ejemplo, el código siguiente tiene una condición de carrera. No garantiza que el intervalo se enumerará antes de que se ejecute el ClearContents
método . Como resultado, la matriz subyacente se borra durante la enumeración del intervalo:
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 sincroniza el acceso a la matriz antes de enumerar el intervalo, como la versión revisada del EnumerateSpan
método lo hace en el ejemplo siguiente, el ClearContents
método no modifica los datos de intervalo subyacentes durante la enumeración. Tenga en cuenta que el ejemplo bloquea la matriz subyacente en la que se basa el intervalo.
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
A diferencia de otras estructuras de enumerador en .NET, :Span<T>.Enumerator
No implementa la IEnumerator interfaz o IEnumerator<T> . Esto se debe a que Span<T>.Enumerator es una estructura ref.
No incluye un
Reset
método , que puede establecer el enumerador en su posición inicial antes del primer elemento del intervalo. (El IEnumerator.Reset() método debe implementarse como parte de la interfaz, pero la mayoría de los implementadores inician una excepción o no proporcionan ninguna implementación).
Propiedades
Current |
Obtiene una referencia al elemento en la posición actual del enumerador. |
Métodos
MoveNext() |
Desplaza el enumerador al siguiente elemento de Span<T>. |