다음을 통해 공유


반복기(C# 및 Visual Basic)

반복기 같은 배열 및 컬렉션을 통해 단계로 사용할 수 있습니다.

반복기 메서드 또는 get 접근자 컬렉션에서 사용자 지정 반복을 수행 합니다. 반복기 메서드를 사용 하는 양보 (Visual Basic) 또는 수익률을 반환 합니다. (C#) 문을 한 번에 각 요소를 반환 합니다. 경우는 Yield 또는 yield return 문에 도달, 코드에서 현재 위치를 기억 됩니다. 실행 위치에서 다음 반복기 함수가 호출 될 때 다시 시작 됩니다.

사용 하 여 클라이언트 코드에서 반복기 소비는 각...다음 (Visual Basic) 또는 foreach (C#) 문 또는 LINQ 쿼리를 사용 하 여.

다음 예제에서 첫 번째 반복의의 For Each 또는 foreach 루프 실행을 계속 하 게는 SomeNumbers 까지 첫 번째 반복기 메서드 Yield 또는 yield return 문에 도달 합니다. 이 반복 3의 값을 반환 하 고 반복기 메서드 내의 현재 위치를 유지 합니다. 루프의 다음 반복을 계속 실행 하는 반복기 메서드에 어디에서 왼쪽에 이르렀을 때를 다시 중지 해제는 Yield 또는 yield return 문. 이 반복 5의 값을 반환 하 고 다시 반복기 메서드 내의 현재 위치를 유지 합니다. 루프 반복기 메서드의 끝에 도달할 때에 완료 됩니다.

Sub Main()
    For Each number As Integer In SomeNumbers()
        Console.Write(number & " ")
    Next 
    ' Output: 3 5 8
    Console.ReadKey()
End Sub 

Private Iterator Function SomeNumbers() As System.Collections.IEnumerable
    Yield 3
    Yield 5
    Yield 8
End Function
static void Main()
{
    foreach (int number in SomeNumbers())
    {
        Console.Write(number.ToString() + " ");
    }
    // Output: 3 5 8
    Console.ReadKey();
}

public static System.Collections.IEnumerable SomeNumbers()
{
    yield return 3;
    yield return 5;
    yield return 8;
}

반복기 메서드 반환 형식 또는 get 접근자 수 IEnumerable, IEnumerable, IEnumerator, 또는 IEnumerator.

사용할 수는 Exit Function 또는 Return 문 (Visual Basic) 또는 yield break 문 (C# 반복 종료 합니다).

A Visual Basic 반복기 함수 또는 get 접근자 선언에 포함 된 반복기 한정자.

반복기는 C#에서 도입 된 Visual Studio 2005, 및에 도입 된 Visual Basic 에서 Visual Studio 2012.

항목 내용

  • 간단한 반복기

  • 컬렉션 클래스 만들기

  • Visual Basic 블록 시도 합니다.

  • Visual Basic 무명 메서드

  • 반복기를 사용 하 여 제네릭 목록으로

  • 구문 정보

  • 기술 구현

  • 반복기 사용

간단한 반복기

다음 예제에서는 단일 한 Yield 또는 yield return 문 내부에 에 대 한...Next (Visual Basic) or for (C#) loop. Main의 각 반복에서 For Each 또는 foreach 문의 본문 옆에 진행 하는 반복기 함수 호출을 만듭니다 Yield 또는 yield return 문.

Sub Main()
    For Each number As Integer In EvenSequence(5, 18)
        Console.Write(number & " ")
    Next 
    ' Output: 6 8 10 12 14 16 18
    Console.ReadKey()
End Sub 

Private Iterator Function EvenSequence(
ByVal firstNumber As Integer, ByVal lastNumber As Integer) _
As System.Collections.Generic.IEnumerable(Of Integer)

    ' Yield even numbers in the range. 
    For number As Integer = firstNumber To lastNumber
        If number Mod 2 = 0 Then
            Yield number
        End If 
    Next 
End Function
static void Main()
{
    foreach (int number in EvenSequence(5, 18))
    {
        Console.Write(number.ToString() + " ");
    }
    // Output: 6 8 10 12 14 16 18
    Console.ReadKey();
}

public static System.Collections.Generic.IEnumerable<int>
    EvenSequence(int firstNumber, int lastNumber)
{
    // Yield even numbers in the range. 
    for (int number = firstNumber; number <= lastNumber; number++)
    {
        if (number % 2 == 0)
        {
            yield return number;
        }
    }
}

컬렉션 클래스 만들기

참고

나머지 예제에 대 한 항목에서을 포함 가져오기 문 (Visual Basic) 또는 를 사용 하 여 에 대 한 지시문 (C#)는 System.CollectionsSystem.Collections.Generic 네임 스페이스.

다음 예제에서는 DaysOfTheWeek 클래스가 구현은 IEnumerable 해야 하는 인터페이스는 GetEnumerator 메서드. 컴파일러가 암시적으로 호출 하는 GetEnumerator 반환 하는 메서드는 IEnumerator.

GetEnumerator 메서드 반환 각 문자열이 한 번 사용 하 여은 Yield 또는 yield return 문. 에 Visual Basic 코드는 Iterator 한정자를 함수 선언에 수.

Sub Main()
    Dim days As New DaysOfTheWeek()
    For Each day As String In days
        Console.Write(day & " ")
    Next 
    ' Output: Sun Mon Tue Wed Thu Fri Sat
    Console.ReadKey()
End Sub 

Private Class DaysOfTheWeek
    Implements IEnumerable

    Public days =
        New String() {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}

    Public Iterator Function GetEnumerator() As IEnumerator _
        Implements IEnumerable.GetEnumerator

        ' Yield each day of the week. 
        For i As Integer = 0 To days.Length - 1
            Yield days(i)
        Next 
    End Function 
End Class
static void Main()
{
    DaysOfTheWeek days = new DaysOfTheWeek();

    foreach (string day in days)
    {
        Console.Write(day + " ");
    }
    // Output: Sun Mon Tue Wed Thu Fri Sat
    Console.ReadKey();
}

public class DaysOfTheWeek : IEnumerable
{
    private string[] days = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };

    public IEnumerator GetEnumerator()
    {
        for (int index = 0; index < days.Length; index++)
        {
            // Yield each day of the week. 
            yield return days[index];
        }
    }
}

다음 예제는 Zoo 동물의 컬렉션을 포함 하는 클래스입니다.

For Each 또는 foreach 클래스 인스턴스를 참조 하는 명령문 (theZoo) 암시적으로 호출을 GetEnumerator 메서드. For Each 또는 foreach 문을 참조 하는 Birds 및 Mammals 속성 사용의 AnimalsForType 반복기 메서드 라는.

Sub Main()
    Dim theZoo As New Zoo()

    theZoo.AddMammal("Whale")
    theZoo.AddMammal("Rhinoceros")
    theZoo.AddBird("Penguin")
    theZoo.AddBird("Warbler")

    For Each name As String In theZoo
        Console.Write(name & " ")
    Next
    Console.WriteLine()
    ' Output: Whale Rhinoceros Penguin Warbler 

    For Each name As String In theZoo.Birds
        Console.Write(name & " ")
    Next
    Console.WriteLine()
    ' Output: Penguin Warbler 

    For Each name As String In theZoo.Mammals
        Console.Write(name & " ")
    Next
    Console.WriteLine()
    ' Output: Whale Rhinoceros

    Console.ReadKey()
End Sub 

Public Class Zoo
    Implements IEnumerable

    ' Private members. 
    Private animals As New List(Of Animal)

    ' Public methods. 
    Public Sub AddMammal(ByVal name As String)
        animals.Add(New Animal With {.Name = name, .Type = Animal.TypeEnum.Mammal})
    End Sub 

    Public Sub AddBird(ByVal name As String)
        animals.Add(New Animal With {.Name = name, .Type = Animal.TypeEnum.Bird})
    End Sub 

    Public Iterator Function GetEnumerator() As IEnumerator _
        Implements IEnumerable.GetEnumerator

        For Each theAnimal As Animal In animals
            Yield theAnimal.Name
        Next 
    End Function 

    ' Public members. 
    Public ReadOnly Property Mammals As IEnumerable
        Get 
            Return AnimalsForType(Animal.TypeEnum.Mammal)
        End Get 
    End Property 

    Public ReadOnly Property Birds As IEnumerable
        Get 
            Return AnimalsForType(Animal.TypeEnum.Bird)
        End Get 
    End Property 

    ' Private methods. 
    Private Iterator Function AnimalsForType( _
    ByVal type As Animal.TypeEnum) As IEnumerable
        For Each theAnimal As Animal In animals
            If (theAnimal.Type = type) Then
                Yield theAnimal.Name
            End If 
        Next 
    End Function 

    ' Private class. 
    Private Class Animal
        Public Enum TypeEnum
            Bird
            Mammal
        End Enum 

        Public Property Name As String 
        Public Property Type As TypeEnum
    End Class 
End Class
static void Main()
{
    Zoo theZoo = new Zoo();

    theZoo.AddMammal("Whale");
    theZoo.AddMammal("Rhinoceros");
    theZoo.AddBird("Penguin");
    theZoo.AddBird("Warbler");

    foreach (string name in theZoo)
    {
        Console.Write(name + " ");
    }
    Console.WriteLine();
    // Output: Whale Rhinoceros Penguin Warbler 

    foreach (string name in theZoo.Birds)
    {
        Console.Write(name + " ");
    }
    Console.WriteLine();
    // Output: Penguin Warbler 

    foreach (string name in theZoo.Mammals)
    {
        Console.Write(name + " ");
    }
    Console.WriteLine();
    // Output: Whale Rhinoceros

    Console.ReadKey();
}

public class Zoo : IEnumerable
{
    // Private members. 
    private List<Animal> animals = new List<Animal>();

    // Public methods. 
    public void AddMammal(string name)
    {
        animals.Add(new Animal { Name = name, Type = Animal.TypeEnum.Mammal });
    }

    public void AddBird(string name)
    {
        animals.Add(new Animal { Name = name, Type = Animal.TypeEnum.Bird });
    }

    public IEnumerator GetEnumerator()
    {
        foreach (Animal theAnimal in animals)
        {
            yield return theAnimal.Name;
        }
    }

    // Public members. 
    public IEnumerable Mammals
    {
        get { return AnimalsForType(Animal.TypeEnum.Mammal); }
    }

    public IEnumerable Birds
    {
        get { return AnimalsForType(Animal.TypeEnum.Bird); }
    }

    // Private methods. 
    private IEnumerable AnimalsForType(Animal.TypeEnum type)
    {
        foreach (Animal theAnimal in animals)
        {
            if (theAnimal.Type == type)
            {
                yield return theAnimal.Name;
            }
        }
    }

    // Private class. 
    private class Animal
    {
        public enum TypeEnum { Bird, Mammal }

        public string Name { get; set; }
        public TypeEnum Type { get; set; }
    }
}

Visual Basic 블록 시도 합니다.

Visual Basic수는 Yield 문에서 Try 블록은 Try...Catch...Finally 문(Visual Basic). A Try 있는 블록은 Yield 문이 있을 수 있습니다 Catch 차단 되지 않으며 가질 수는 Finally 블록.

C# 정보C# 정보

C# 수는 yield return 문에서 try 블록은 try-finally 문.A try 가 블록은 yield return 문 하나를 가질 수 없습니다 catch 블록.

다음 Visual Basic 예제 포함 Try, Catch, 및 Finally 는 반복기 함수에서 차단 합니다. Finally 반복기 함수에서 블록을 실행 하기 전에 For Each 반복 완료 합니다.

Sub Main()
    For Each number As Integer In Test()
        Console.WriteLine(number)
    Next
    Console.WriteLine("For Each is done.")

    ' Output: 
    '  3 
    '  4 
    '  Something happened. Yields are done. 
    '  Finally is called. 
    '  For Each is done.
    Console.ReadKey()
End Sub 

Private Iterator Function Test() As IEnumerable(Of Integer)
    Try
        Yield 3
        Yield 4
        Throw New Exception("Something happened. Yields are done.")
        Yield 5
        Yield 6
    Catch ex As Exception
        Console.WriteLine(ex.Message)
    Finally
        Console.WriteLine("Finally is called.")
    End Try 
End Function

A Yield 문 안 내는 Catch 블록 또는 Finally 블록.

경우는 For Each 본문 (반복기 메서드) 대신 예외를 throw 한 Catch 블록 반복기 함수에서 실행 되지 않습니다 있지만 Finally 반복기 함수에서 블록이 실행. A Catch 는 반복기 함수 블록 catch 반복기 함수 안에서 발생 하는 예외에 대해서만 합니다.

Visual Basic 무명 메서드

Visual Basic (있지만 C#), 익명 함수는 반복기 함수가 될 수 있습니다. 다음은 이에 대한 예입니다.

Dim iterateSequence = Iterator Function() _
                      As IEnumerable(Of Integer)
                          Yield 1
                          Yield 2
                      End Function 

For Each number As Integer In iterateSequence()
    Console.Write(number & " ")
Next 
' Output: 1 2
Console.ReadKey()

다음 Visual Basic 예 비 반복기 메서드 인수의 유효성을 검사 했습니다. 컬렉션 요소에 설명 하는 익명 반복기의 결과 메서드를 반환 합니다.

Sub Main()
    For Each number As Integer In GetSequence(5, 10)
        Console.Write(number & " ")
    Next 
    ' Output: 5 6 7 8 9 10
    Console.ReadKey()
End Sub 

Public Function GetSequence(ByVal low As Integer, ByVal high As Integer) _
As IEnumerable
    ' Validate the arguments. 
    If low < 1 Then 
        Throw New ArgumentException("low is too low")
    End If 
    If high > 140 Then 
        Throw New ArgumentException("high is too high")
    End If 

    ' Return an anonymous iterator function. 
    Dim iterateSequence = Iterator Function() As IEnumerable
                              For index = low To high
                                  Yield index
                              Next 
                          End Function 
    Return iterateSequence()
End Function

유효성 검사 함수 안에서 반복기 이면 유효성 검사의 첫 번째 반복을 시작할 때까지 수행할 수 없습니다는 For Each 본문입니다.

반복기를 사용 하 여 제네릭 목록으로

다음 예제에서는 Stack(Of T) 제네릭 클래스 구현에서 IEnumerable 제네릭 인터페이스. Push 메서드는 값 형식의 배열을 할당 T. GetEnumerator 메서드를 사용 하 여 배열 값을 반환 된 Yield 또는 yield return 문.

원본 외에도 GetEnumerator 메서드, 제네릭이 아닌 GetEnumerator 메서드 구현 해야 합니다. 이 때문에 IEnumerable 상속 IEnumerable. 제네릭이 아닌 구현은 제네릭 구현으로 연기합니다.

예제 명명 된 반복기를 사용 하 여 동일한 데이터 컬렉션을 통해 반복할 수 있는 다양 한 방법을 지원 하기 위해. 이러한 반복기 이라는 TopToBottom 및 BottomToTop 속성 및 TopN 메서드.

BottomToTop 속성 사용에 대 한 반복기는 get 접근자입니다. 에 Visual Basic 코드는 속성 선언이 포함의 Iterator 키워드.

Sub Main()
    Dim theStack As New Stack(Of Integer)

    ' Add items to the stack. 
    For number As Integer = 0 To 9
        theStack.Push(number)
    Next 

    ' Retrieve items from the stack. 
    ' For Each is allowed because theStack implements 
    ' IEnumerable(Of Integer). 
    For Each number As Integer In theStack
        Console.Write("{0} ", number)
    Next
    Console.WriteLine()
    ' Output: 9 8 7 6 5 4 3 2 1 0 

    ' For Each is allowed, because theStack.TopToBottom 
    ' returns IEnumerable(Of Integer). 
    For Each number As Integer In theStack.TopToBottom
        Console.Write("{0} ", number)
    Next
    Console.WriteLine()
    ' Output: 9 8 7 6 5 4 3 2 1 0 

    For Each number As Integer In theStack.BottomToTop
        Console.Write("{0} ", number)
    Next
    Console.WriteLine()
    ' Output: 0 1 2 3 4 5 6 7 8 9  

    For Each number As Integer In theStack.TopN(7)
        Console.Write("{0} ", number)
    Next
    Console.WriteLine()
    ' Output: 9 8 7 6 5 4 3

    Console.ReadKey()
End Sub 

Public Class Stack(Of T)
    Implements IEnumerable(Of T)

    Private values As T() = New T(99) {}
    Private top As Integer = 0

    Public Sub Push(ByVal t As T)
        values(top) = t
        top = top + 1
    End Sub 

    Public Function Pop() As T
        top = top - 1
        Return values(top)
    End Function 

    ' This function implements the GetEnumerator method. It allows 
    ' an instance of the class to be used in a For Each statement. 
    Public Iterator Function GetEnumerator() As IEnumerator(Of T) _
        Implements IEnumerable(Of T).GetEnumerator

        For index As Integer = top - 1 To 0 Step -1
            Yield values(index)
        Next 
    End Function 

    Public Iterator Function GetEnumerator1() As IEnumerator _
        Implements IEnumerable.GetEnumerator

        Yield GetEnumerator()
    End Function 

    Public ReadOnly Property TopToBottom() As IEnumerable(Of T)
        Get 
            Return Me 
        End Get 
    End Property 

    Public ReadOnly Iterator Property BottomToTop As IEnumerable(Of T)
        Get 
            For index As Integer = 0 To top - 1
                Yield values(index)
            Next 
        End Get 
    End Property 

    Public Iterator Function TopN(ByVal itemsFromTop As Integer) _
        As IEnumerable(Of T)

        ' Return less than itemsFromTop if necessary. 
        Dim startIndex As Integer =
            If(itemsFromTop >= top, 0, top - itemsFromTop)

        For index As Integer = top - 1 To startIndex Step -1
            Yield values(index)
        Next 
    End Function 
End Class
static void Main()
{
    Stack<int> theStack = new Stack<int>();

    //  Add items to the stack. 
    for (int number = 0; number <= 9; number++)
    {
        theStack.Push(number);
    }

    // Retrieve items from the stack. 
    // foreach is allowed because theStack implements 
    // IEnumerable<int>. 
    foreach (int number in theStack)
    {
        Console.Write("{0} ", number);
    }
    Console.WriteLine();
    // Output: 9 8 7 6 5 4 3 2 1 0 

    // foreach is allowed, because theStack.TopToBottom 
    // returns IEnumerable(Of Integer). 
    foreach (int number in theStack.TopToBottom)
    {
        Console.Write("{0} ", number);
    }
    Console.WriteLine();
    // Output: 9 8 7 6 5 4 3 2 1 0 

    foreach (int number in theStack.BottomToTop)
    {
        Console.Write("{0} ", number);
    }
    Console.WriteLine();
    // Output: 0 1 2 3 4 5 6 7 8 9 

    foreach (int number in theStack.TopN(7))
    {
        Console.Write("{0} ", number);
    }
    Console.WriteLine();
    // Output: 9 8 7 6 5 4 3

    Console.ReadKey();
}

public class Stack<T> : IEnumerable<T>
{
    private T[] values = new T[100];
    private int top = 0;

    public void Push(T t)
    {
        values[top] = t;
        top++;
    }
    public T Pop()
    {
        top--;
        return values[top];
    }

    // This method implements the GetEnumerator method. It allows 
    // an instance of the class to be used in a foreach statement. 
    public IEnumerator<T> GetEnumerator()
    {
        for (int index = top - 1; index >= 0; index--)
        {
            yield return values[index];
        }
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

    public IEnumerable<T> TopToBottom
    {
        get { return this; }
    }

    public IEnumerable<T> BottomToTop
    {
        get
        {
            for (int index = 0; index <= top - 1; index++)
            {
                yield return values[index];
            }
        }
    }

    public IEnumerable<T> TopN(int itemsFromTop)
    {
        // Return less than itemsFromTop if necessary. 
        int startIndex = itemsFromTop >= top ? 0 : top - itemsFromTop;

        for (int index = top - 1; index >= startIndex; index--)
        {
            yield return values[index];
        }
    }

}

구문 정보

반복기를 메서드로 발생할 수 있습니다 또는 get 접근자입니다. 반복기는 이벤트, 인스턴스 생성자, 정적 생성자 또는 정적 소멸자에서 발생할 수 없습니다.

식 형식에서 암시적 변환이 존재 해야는 Yield (Visual Basic) 또는 yield return (C#) 문은 반복기의 반환 형식입니다.

Visual Basic, 반복기 메서드를 사용할 수 없습니다 ByRef 매개 변수입니다. C#는 반복기 메서드에 사용할 수 없습니다 ref 또는 out 매개 변수입니다.

Visual Basic, "Yield"는 예약어 이며에서 사용 될 때 특별 한 의미를 갖는 Iterator 메서드 또는 get 접근자입니다. C#에서 "yield" 예약어 되지 않고 그 전에 사용할 경우에 특별 한 의미가 있는 return 또는 break 키워드입니다.

기술 구현

반복기를 메서드로 작성해도 컴파일러에서는 반복기를 중첩된 클래스, 즉 상태 시스템으로 변환합니다. 이 클래스는 동안 반복기의 위치를 추적 For Each...Next 또는 foreach 클라이언트 코드에서 루프가 계속 됩니다.

컴파일러의 기능을 확인 하려면 Ildasm.exe 도구 사용 하 여 반복기 메서드에 대해 생성 된 Microsoft 중간 언어 코드를 보려면.

반복기를 만들도록 한 클래스 또는 구조체, 전체를 구현 하지 않아도 IEnumerator 인터페이스. 컴파일러가 반복기가 발견 되 면 자동으로 생성의 Current, MoveNext, 및 Dispose 메서드는 IEnumerator 또는 IEnumerator 인터페이스.

각 연속 반복에는 For Each…Next 또는 foreach 루프 (또는 직접 호출이 IEnumerator.MoveNext), 다음 반복기 코드 본문을 이전 한 후 다시 시작 Yield 또는 yield return 문. 다음 다음으로 계속 Yield 또는 yield return 반복기 본문의 끝에 도달할 때까지 문을 또는까지 Exit Function 또는 Return 문 (Visual Basic) 또는 yield break (C#) 문이 있습니다.

반복기는 IEnumerator.Reset 메서드를 지원하지 않습니다. 처음부터 다시 반복 하려면 새 반복기를 가져와야 합니다.

자세한 내용은 Visual Basic 언어 사양 또는 C# 언어 사양.

반복기 사용

반복기 사용의 단순성을 유지 하는 For Each 반복 하면 복잡 한 코드를 사용 하 여 목록 순서를 채울 수 있습니다. 다음 작업을 수행 하려는 경우에 유용할 수 있습니다.

  • 후 첫 번째 목록 시퀀스 수정 For Each 루프 반복 합니다.

  • 큰 목록의 첫 번째 반복 하기 전에 완전히 로드 되지 않도록 방지는 For Each 루프. 예를 들어 일괄 처리 테이블의 행을 로드 하는 페이징된 반입입니다. 또 다른 예로 EnumerateFiles .NET Framework 내에서 반복기를 구현 하는 메서드.

  • 반복기에 목록 작성을 캡슐화 합니다. 반복기 메서드를 목록을 만들고 각 루프에서 결과 얻을 수 있습니다.

다음 C# 블로그 반복기를 사용 하는 방법에 대 한 추가 정보를 제공합니다.

참고 항목

참조

For Each...Next 문(Visual Basic)

foreach, in(C# 참조)

Yield 문(Visual Basic)

yield(C# 참조)

반복기(Visual Basic)

배열에 foreach 사용(C# 프로그래밍 가이드)

제네릭(C# 프로그래밍 가이드)

System.Collections.Generic

IEnumerable