Span<T>.Enumerator Struktur
Definition
Wichtig
Einige Informationen beziehen sich auf Vorabversionen, die vor dem Release ggf. grundlegend überarbeitet werden. Microsoft übernimmt hinsichtlich der hier bereitgestellten Informationen keine Gewährleistungen, seien sie ausdrücklich oder konkludent.
Stellt einen Enumerator für diese Elemente eines Span<T>-Elements bereit.
public: value class Span<T>::Enumerator
public ref struct Span<T>.Enumerator
type Span<'T>.Enumerator = struct
Public Structure Span(Of T).Enumerator
Typparameter
- T
- Vererbung
Hinweise
Der C# -Foreach der Sprache C# und der For Each... Das nächste Konstrukt in Visual Basic blendet die Komplexität von Enumeratoren aus. Anstatt den Enumerator direkt zu bearbeiten, wird die Verwendung von foreach
oder For Each...Next
empfohlen.
Zunächst wird der Enumerator vor dem ersten Element im Span<T>positioniert. An dieser Position ist Current nicht definiert. Sie müssen aufrufen MoveNext , um den Enumerator zum ersten Element in der zu wechseln, Span<T> bevor Sie den Wert von Currentlesen.
Current gibt den gleichen Wert zurück, bis MoveNext aufgerufen wird. MoveNextwird auf das nächste Element im Span<T>festgelegtCurrent.
Wenn MoveNext das Ende von Span<T>übergibt, MoveNext gibt zurück false
. Wenn sich der Enumerator in diesem Zustand befindet, werden nachfolgende Aufrufe von MoveNext ebenfalls zurückgegeben false
und Current sind nicht definiert. Sie können nicht auf das erste Element im Span<T> erneut festlegenCurrent. Stattdessen müssen Sie eine neue Enumeratorinstanz erstellen.
Der Enumerator hat keinen exklusiven Zugriff auf .Span<T> Darüber hinaus können die zugrunde liegenden Daten, auf denen die Spanne basiert, auch geändert werden. Daher ist das Aufzählen durch eine Spanne intrinsisch kein threadsicheres Verfahren. Um die Threadsicherheit während der Enumeration zu gewährleisten, müssen Sie eine eigene Synchronisierung implementieren. Der folgende Code weist beispielsweise eine Racebedingung auf. Es wird nicht sichergestellt, dass die Spanne aufgelistet wird, bevor die ClearContents
Methode ausgeführt wird. Daher wird das zugrunde liegende Array während der Enumeration der Spanne gelöscht:
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
Wenn Sie den Zugriff auf das Array vor dem Aufzählen der Spanne synchronisieren, wie dies in der überarbeiteten Version der EnumerateSpan
Methode im folgenden Beispiel der Fall ist, ändert die Methode während der ClearContents
Enumeration keine zugrunde liegenden span-Daten. Beachten Sie, dass im Beispiel das zugrunde liegende Array gesperrt wird, auf dem die Spanne basiert.
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
Im Gegensatz zu einigen anderen Enumeratorstrukturen in .NET ist :Span<T>.Enumerator
Implementiert die IEnumerator -Schnittstelle oder IEnumerator<T> nicht. Dies liegt daran, dass Span<T>.Enumerator eine Verweisstruktur ist.
Enthält
Reset
keine -Methode, die den Enumerator auf seine Anfangsposition vor dem ersten Element in der Spanne festlegen kann. (Die IEnumerator.Reset() -Methode muss als Teil der -Schnittstelle implementiert werden, aber die meisten Implementierer lösen entweder eine Ausnahme aus oder stellen keine Implementierung bereit.)
Eigenschaften
Current |
Ruft einen Verweis auf das Element an der aktuellen Position des Enumerators ab. |
Methoden
MoveNext() |
Legt den Enumerator auf das nächste Element von Span<T> fest. |