Span<T>.Enumerator 结构

定义

Span<T> 的元素提供枚举器。Provides an enumerator for the elements of a Span<T>.

public: value class Span<T>::Enumerator
public struct Span<T>.Enumerator
type Span<'T>.Enumerator = struct
Public Structure Span(Of T).Enumerator

类型参数

T
继承
Span<T>.Enumerator

注解

语言的foreach和 For Each ... C# C# Visual Basic 中的下一个构造隐藏了枚举器的复杂性。The C# foreach of the C# language and the For Each...Next construct in Visual Basic hides the complexity of enumerators. 建议使用foreachFor Each...Next ,而不是直接操作枚举器。Instead of directly manipulating the enumerator, using foreach or For Each...Next is recommended.

最初,枚举器位于中Span<T>第一个元素之前。Initially, the enumerator is positioned before the first element in the Span<T>. 在此位置上,未定义 CurrentAt this position, Current is undefined. 在读取的MoveNext值之前,Span<T>必须调用以将枚举器前进到中的第一项CurrentYou must call MoveNext to advance the enumerator to the first item in the Span<T> before reading the value of Current.

Current在调用之前MoveNext ,返回相同的值。Current returns the same value until MoveNext is called. MoveNext设置CurrentSpan<T>中的下一项。MoveNext sets Current to the next item in the Span<T>.

如果MoveNext传递的末尾Span<T>MoveNext则返回falseIf MoveNext passes the end of the Span<T>, MoveNext returns false. 当枚举器处于此状态时,对MoveNext的后续调用也将返回false并且Current未定义。When the enumerator is at this state, subsequent calls to MoveNext also return false and Current is undefined. 您不能Current Span<T>再次将设置为中的第一项; 您必须改为创建新的枚举器实例。You cannot set Current to the first item in the Span<T> again; you must create a new enumerator instance instead.

枚举器没有对的Span<T>独占访问权限。The enumerator does not have exclusive access to the Span<T>. 此外,还可以修改范围所基于的基础数据。In addition, the underlying data on which the span is based can also be modified. 因此,在范围内进行枚举本质上并不是一个线程安全的过程。Therefore, enumerating through a span is intrinsically not a thread-safe procedure. 若要保证枚举过程中的线程安全,必须实现自己的同步。To guarantee thread safety during enumeration, you must implement your own synchronization. 例如,下面的代码具有争用条件。For example, the following code has a race condition. 它不会确保在执行ClearContents方法之前枚举跨距。It does not ensure that the span will be enumerated before the ClearContents method executes. 因此,在枚举范围期间将清除基础数组:As a result, the underlying array is cleared during enumeration of the span:

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

如果在枚举范围之前同步对数组的访问,则在下面的示例中EnumerateSpan ClearContents ,方法的修改后的版本将不会修改基础范围内的数据。If you synchronize access to the array before enumerating the span, as the revised version of the EnumerateSpan method does in the following example, the ClearContents method doesn't modify underlying span data during enumeration. 请注意,该示例将锁定范围所基于的基础数组。Note that the example locks the underlying array on which the span is based.

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

不同于 .NET 中的Span<T>.Enumerator其他枚举器结构,:Unlike some other enumerator structures in .NET, the Span<T>.Enumerator:

  • 不实现IEnumeratorIEnumerator<T>接口。Does not implement the IEnumerator or IEnumerator<T> interface. 这是因为Span<T>.Enumeratorref 结构This is because Span<T>.Enumerator is a ref struct.

  • 不包括Reset方法,该方法可将枚举数设置为其在范围中第一个元素之前的初始位置。Does not include a Reset method, which can set the enumerator to its initial position before the first element in the span. IEnumerator.Reset() (方法必须作为接口的一部分来实现,但大多数实现者会引发异常或不提供实现。)(The IEnumerator.Reset() method must be implemented as part of the interface, but most implementors either throw an exception or provide no implementation.)

属性

Current

获取对枚举器当前位置的项目的引用。Gets a reference to the item at the current position of the enumerator.

方法

MoveNext()

将枚举器推进到 Span<T> 的下一项。Advances the enumerator to the next item of the Span<T>.

适用于