Span<T>.Enumerator Struct
Definizione
Importante
Alcune informazioni sono relative alla release non definitiva del prodotto, che potrebbe subire modifiche significative prima della release definitiva. Microsoft non riconosce alcuna garanzia, espressa o implicita, in merito alle informazioni qui fornite.
Fornisce un enumeratore per gli elementi di 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
Parametri di tipo
- T
- Ereditarietà
Commenti
Foreach C# del linguaggio C# e For Each... Il costrutto successivo in Visual Basic nasconde la complessità degli enumeratori. Anziché modificare direttamente l'enumeratore, usando foreach
o For Each...Next
è consigliabile.
Inizialmente, l'enumeratore viene posizionato prima del primo elemento in Span<T>. In questa posizione, la proprietà Current è indefinita. È necessario chiamare MoveNext per avanzare l'enumeratore al primo elemento nell'oggetto Span<T> prima di leggere il valore di Current.
Current restituisce lo stesso valore finché non MoveNext viene chiamato. MoveNext imposta Current sull'elemento successivo in Span<T>.
Se MoveNext passa la fine di Span<T>, MoveNext restituisce false
. Quando l'enumeratore si trova in questo stato, le chiamate successive per MoveNext restituire false
e Current non sono definito. Non è possibile impostare Current nuovamente il primo elemento. È necessario creare invece una nuova istanza dell'enumeratore Span<T> .
L'enumeratore non ha accesso esclusivo all'oggetto Span<T>. Inoltre, i dati sottostanti su cui è basato l'intervallo possono anche essere modificati. Di conseguenza, l'enumerazione tramite un intervallo non è intrinsecamente una procedura thread-safe. Per garantire la sicurezza dei thread durante l'enumerazione, è necessario implementare la sincronizzazione personalizzata. Ad esempio, il codice seguente ha una condizione di gara. Non garantisce che l'intervallo venga enumerato prima dell'esecuzione del ClearContents
metodo. Di conseguenza, la matrice sottostante viene cancellata durante l'enumerazione dell'intervallo:
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
Se si sincronizza l'accesso alla matrice prima di enumerare l'intervallo, poiché la versione modificata del EnumerateSpan
metodo viene eseguita nell'esempio seguente, il ClearContents
metodo non modifica i dati dell'intervallo sottostante durante l'enumerazione. Si noti che l'esempio blocca la matrice sottostante in cui si basa l'intervallo.
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 differenza di altre strutture dell'enumeratore in .NET, l'oggetto Span<T>.Enumerator:
Non implementa l'interfaccia IEnumerator o IEnumerator<T> . Questo perché è Span<T>.Enumerator uno struct di riferimento.
Non include un
Reset
metodo, che può impostare l'enumeratore sulla posizione iniziale prima del primo elemento nell'intervallo. Il IEnumerator.Reset() metodo deve essere implementato come parte dell'interfaccia, ma la maggior parte degli implementori genera un'eccezione o non fornisce alcuna implementazione.
Proprietà
Current |
Restituisce un riferimento all'elemento in corrispondenza della posizione corrente dell'enumeratore. |
Metodi
MoveNext() |
Sposta l'enumeratore all'elemento successivo dell'oggetto Span<T>. |