Span<T>.Enumerator 結構
定義
重要
部分資訊涉及發行前產品,在發行之前可能會有大幅修改。 Microsoft 對此處提供的資訊,不做任何明確或隱含的瑕疵擔保。
提供一個 元素的 Span<T>列舉子。
public: value class Span<T>::Enumerator : System::Collections::Generic::IEnumerator<T>
public: value class Span<T>::Enumerator
public ref struct Span<T>.Enumerator : System.Collections.Generic.IEnumerator<T>
public ref struct Span<T>.Enumerator
type Span<'T>.Enumerator = struct
interface IEnumerator<'T>
interface IEnumerator
interface IDisposable
type Span<'T>.Enumerator = struct
Public Structure Span(Of T).Enumerator
Implements IEnumerator(Of T)
Public Structure Span(Of T).Enumerator
類型參數
- T
- 繼承
- 實作
備註
C# 語言中的 C# foreach 以及 Foreach...」Next Visual Basic 中的結構隱藏了列舉器的複雜性。 建議不要直接操作列舉器,而是使用 foreach 或 For Each...Next 。
最初,列舉器會被放置在 Span<T>。 在此位置, Current 未定義。 你必須先呼叫MoveNext,讓列舉員在讀取 的值Current之前,先將列舉器推進到第一個項目Span<T>。
Current 回傳相同的值直到 MoveNext 被呼叫。 MoveNext 設定 Current 為 中的下一個項目 Span<T>。
若 MoveNext 通過 Span<T>, MoveNext 則返回 false。 當列舉器處於此狀態時,後續的回MoveNext傳falseCurrent呼叫也為未定義。 你不能在 back 裡Span<T>設Current成第一個項目;你必須建立一個新的 enumerator 實例。
列舉器並非對 的專屬存取 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 OR IEnumerator<T> 介面。 這是因為 Span<T>.Enumerator 是 ref struct。
不包含
Reset一種方法,可以將列舉器設定為張成第一個元素之前的初始位置。 (該 IEnumerator.Reset() 方法必須作為介面的一部分實作,但大多數實作者要麼拋出例外,要麼不提供實作。)
屬性
| 名稱 | Description |
|---|---|
| Current |
會取得列舉器當前位置的項目參考。 |
方法
| 名稱 | Description |
|---|---|
| MoveNext() |
將列舉器推進到下一個項目 Span<T>。 |
明確介面實作
| 名稱 | Description |
|---|---|
| IDisposable.Dispose() |
執行與釋放、釋放或重置未管理資源相關的應用程式定義任務。 |
| IEnumerator.Current |
取得集合中位於列舉值目前位置的專案。 |
| IEnumerator.Reset() |
將列舉值設定為其初始位置,也就是集合中第一個專案之前。 |
| IEnumerator<T>.Current |
取得集合中位於列舉值目前位置的專案。 |