Span<T>.Enumerator 結構
定義
重要
部分資訊涉及發行前產品,在發行之前可能會有大幅修改。 Microsoft 對此處提供的資訊,不做任何明確或隱含的瑕疵擔保。
提供 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# 語言的 C# foreach 和 For Each...Visual Basic 中的下一個 建構會隱藏列舉值的複雜度。 不建議使用 foreach
或 For Each...Next
直接操作列舉值。
一開始,列舉值位於 中的 Span<T> 第一個專案之前。 在這個位置上,Current 並未定義。 您必須呼叫 MoveNext ,才能將列舉值前進至 中的 Span<T> 第一個專案,再讀取 的值 Current 。
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 是 ref 結構。
不包含 方法,此方法可以將列舉值設定為範圍中第一個專案
Reset
之前的初始位置。 (IEnumerator.Reset() 方法必須實作為介面的一部分,但大部分實作者都會擲回例外狀況,或未提供任何實作。)
屬性
Current |
取得位於目前列舉值位置的項目參考。 |
方法
MoveNext() |
將列舉值前移至 Span<T> 的下一個項目。 |