Span<T>.Enumerator 結構

定義

提供 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
繼承
Span<T>.Enumerator

備註

C# 語言的 C# foreachFor Each...Visual Basic 中的下一個 建構會隱藏列舉值的複雜度。 不建議使用 foreachFor Each...Next 直接操作列舉值。

一開始,列舉值位於 中的 Span<T> 第一個專案之前。 在這個位置上,Current 並未定義。 您必須呼叫 MoveNext ,才能將列舉值前進至 中的 Span<T> 第一個專案,再讀取 的值 Current

Current 會傳回相同的值,直到呼叫為止 MoveNextMoveNext 會將 設定 Current 為 中的 Span<T> 下一個專案。

如果 MoveNext 傳遞 的 Span<T> 結尾, MoveNext 則會傳 false 回 。 當列舉值處於這個狀態時,後續對 MoveNext 的呼叫也會傳回 falseCurrent 未定義。 您無法再次設定 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

屬性

Current

取得位於目前列舉值位置的項目參考。

方法

MoveNext()

將列舉值前移至 Span<T> 的下一個項目。

適用於