Span<T>.Enumerator Struktura
Definicja
Ważne
Niektóre informacje odnoszą się do produktu w wersji wstępnej, który może zostać znacząco zmodyfikowany przed wydaniem. Firma Microsoft nie udziela żadnych gwarancji, jawnych lub domniemanych, w odniesieniu do informacji podanych w tym miejscu.
Udostępnia moduł wyliczający dla elementów elementu 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
Parametry typu
- T
- Dziedziczenie
Uwagi
Foreach języka C# języka C# i dla każdego... Następna konstrukcja w Visual Basic ukrywa złożoność modułów wyliczania. Zamiast bezpośrednio manipulować modułem wyliczającym, zaleca się użycie foreach
lub For Each...Next
zalecane.
Początkowo moduł wyliczający jest umieszczony przed pierwszym elementem w elemecie Span<T>. Na tym stanowisku Current jest niezdefiniowany. Musisz wywołać metodę MoveNext , aby przejść do pierwszego elementu w elemencie Span<T> przed odczytaniem wartości Current.
Current zwraca tę samą wartość, dopóki MoveNext nie zostanie wywołana. MoveNext ustawia Current wartość na następny element w elemencie Span<T>.
Jeśli MoveNext przejdzie koniec elementu Span<T>, MoveNext zwraca wartość false
. Gdy moduł wyliczający znajduje się w tym stanie, kolejne wywołania do MoveNext zwrócenia false
i Current są niezdefiniowane. Nie można ustawić Current pierwszego elementu na Span<T> ponownie. Zamiast tego należy utworzyć nowe wystąpienie modułu wyliczającego.
Moduł wyliczający nie ma wyłącznego dostępu do elementu Span<T>. Ponadto bazowe dane, na których opiera się zakres, można również modyfikować. W związku z tym wyliczanie przez zakres nie jest wewnętrznie procedurą bezpieczną wątkowo. Aby zagwarantować bezpieczeństwo wątków podczas wyliczania, należy zaimplementować własną synchronizację. Na przykład poniższy kod ma warunek wyścigu. Nie gwarantuje ona, że zakres zostanie wyliczony przed wykonaniem ClearContents
metody. W rezultacie macierz bazowa jest czyszczone podczas wyliczania zakresu:
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
Jeśli zsynchronizuj dostęp do tablicy przed wyliczeniem zakresu, ponieważ poprawiona wersja EnumerateSpan
metody ma zastosowanie w poniższym przykładzie, ClearContents
metoda nie modyfikuje danych zakresu bazowego podczas wyliczania. Należy pamiętać, że przykład blokuje macierz bazową, na której opiera się zakres.
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
W przeciwieństwie do niektórych innych struktur wyliczania na platformie .NET:Span<T>.Enumerator
Nie implementuje interfejsu IEnumerator lub IEnumerator<T> . Jest to spowodowane tym, że Span<T>.Enumerator jest strukturą ref.
Nie zawiera
Reset
metody, która może ustawić moduł wyliczający na jego pozycję początkową przed pierwszym elementem w zakresie. (Metoda IEnumerator.Reset() musi być zaimplementowana w ramach interfejsu, ale większość implementatorów zgłasza wyjątek lub nie zapewnia implementacji).
Właściwości
Current |
Pobiera odwołanie do elementu w bieżącej pozycji modułu wyliczającego. |
Metody
MoveNext() |
Rozwija moduł wyliczający do następnego elementu .Span<T> |