다음을 통해 공유


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# 언어 및 For Each의 C# foreach... Visual Basic의 다음 구문은 열거자의 복잡성을 숨깁니다. 열거자를 직접 조작하는 대신 사용 foreach 하거나 For Each...Next 사용하는 것이 좋습니다.

처음에는 열거자가 의 첫 번째 요소 Span<T>앞에 배치됩니다. 이 위치에서 Current는 정의되지 않습니다. 값을 Current읽기 전에 열거자를 첫 번째 항목으로 Span<T> 이동하려면 호출 MoveNext 해야 합니다.

Current 는 호출될 때까지 MoveNext 동일한 값을 반환합니다. MoveNext에서 다음 항목으로 Span<T>설정합니다Current.

의 끝을 통과하면 MoveNext .를 Span<T>MoveNext 반환합니다false. 열거자가 이 상태에 있으면 후속 호출도 반환 false 되고 MoveNext Current 정의되지 않습니다. 다시 첫 번째 항목 Span<T> 으로 설정할 Current 수 없습니다. 대신 새 열거자 인스턴스를 만들어야 합니다.

열거자에는 .에 대한 단독 액세스 권한이 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

다음 예제 ClearContents 에서 수정된 버전의 EnumerateSpan 메서드처럼 범위를 열거하기 전에 배열에 대한 액세스를 동기화하는 경우 메서드는 열거 중에 기본 범위 데이터를 수정하지 않습니다. 이 예제에서는 범위의 기반이 되는 기본 배열을 잠가 둡니다.

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<T> 인터페이스를 IEnumerator 구현하지 않습니다. 이는 ref 구조체이기 때문 Span<T>.Enumerator 입니다.

  • 열거자를 범위의 첫 번째 요소 앞의 초기 위치로 설정할 수 있는 메서드를 포함하지 Reset 않습니다. (메서드는 IEnumerator.Reset() 인터페이스의 일부로 구현되어야 하지만 대부분의 구현자는 예외를 throw하거나 구현을 제공하지 않습니다.)

속성

Current

열거자의 현재 위치에 있는 항목에 대한 참조를 가져옵니다.

메서드

MoveNext()

열거자를 Span<T>의 다음 항목으로 이동합니다.

적용 대상