Udostępnij za pośrednictwem


For Each...Next — Instrukcja (Visual Basic)

Powtarza grupę poleceń dla każdego elementu w kolekcji.

For Each element [ As datatype ] In group
    [ statements ]
    [ Continue For ]
    [ statements ]
    [ Exit For ]
    [ statements ]
Next [ element ]

Części

Termin

Definicja

element

Wymagane w For Each instrukcji.Opcjonalnie w Next instrukcji.Zmienna.Używane do iteracji elementów w kolekcji.

datatype

Wymagany, jeżeli element nie jest już zadeklarowany.Typ danych z element.

group

Wymagane.Zmienna typu, który jest typem kolekcji lub obiektu.Odnosi się do kolekcji, przez który statements będą powtarzane.

statements

Opcjonalne.Jeden lub więcej instrukcji między For Each i Next które są uruchamiane każdego elementu w group.

Continue For

Opcjonalne.Przekazuje sterowanie do początku For Each pętli.

Exit For

Opcjonalne.Przekazuje sterowanie z For Each pętli.

Next

Wymagane.Kończy definicję For Each pętli.

Prosty przykład

Use a For Each...Next pętli, kiedy mają być powtarzane zestaw instrukcje dla każdego elementu w kolekcji lub tablicy.

PoradaPorada

A For...Next — Instrukcja (Visual Basic) działa dobrze, kiedy można skojarzyć każdej iteracji pętli ze zmiennej kontrolnej i określenia wartości początkowych i końcowych tej zmiennej.Jednak gdy mamy do czynienia z kolekcją, pojęcie wartości początkowych i końcowych nie ma sensu, a użytkownik nie musi wiedzieć, ile elementów kolekcji.W tego rodzaju przypadku For Each...Next pętli jest często lepszym rozwiązaniem.

W poniższym przykładzie For Each...Next instrukcji iterację wszystkich elementów kolekcji List.

' Create a list of strings by using a 
' collection initializer. 
Dim lst As New List(Of String) _
    From {"abc", "def", "ghi"}

' Iterate through the list. 
For Each item As String In lst
    Debug.Write(item & " ")
Next
Debug.WriteLine("")
'Output: abc def ghi

Aby uzyskać więcej przykładów, zobacz Kolekcje (C# i Visual Basic) i Tablice w Visual Basic.

Zagnieżdżonej pętli

Można zagnieździć For Each pętli poprzez umieszczenie jednej pętli w innym.

W poniższym przykładzie zademonstrowano zagnieżdżonych For Each...Next struktur.

' Create lists of numbers and letters 
' by using array initializers. 
Dim numbers() As Integer = {1, 4, 7}
Dim letters() As String = {"a", "b", "c"}

' Iterate through the list by using nested loops. 
For Each number As Integer In numbers
    For Each letter As String In letters
        Debug.Write(number.ToString & letter & " ")
    Next 
Next
Debug.WriteLine("")
'Output: 1a 1b 1c 4a 4b 4c 7a 7b 7c 

Zagnieżdżenie pętle każdej pętli musi mieć wyjątkowy element zmiennej.

Można także zagnieżdżać różne rodzaje struktur sterujących w sobie zagnieżdżone.Aby uzyskać więcej informacji, zobacz Zagnieżdżone struktury sterujące (Visual Basic).

Exit dla i kontynuuj przez

Wyjście dla instrukcja powoduje wykonanie zakończyć pracę For...Next pętli i transfery sterowania do instrukcji następującej Next instrukcji.

Continue For Instrukcji przekazuje sterowanie od razu do następnej iteracji pętli.Aby uzyskać więcej informacji, zobacz Continue — Instrukcja (Visual Basic).

Poniższy przykład pokazuje, jak używać Continue For i Exit For instrukcji.

Dim numberSeq() As Integer =
    {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}

For Each number As Integer In numberSeq
    ' If number is between 5 and 7, continue 
    ' with the next iteration. 
    If number >= 5 And number <= 8 Then 
        Continue For 
    End If 

    ' Display the number.
    Debug.Write(number.ToString & " ")

    ' If number is 10, exit the loop. 
    If number = 10 Then 
        Exit For 
    End If 
Next
Debug.WriteLine("")
' Output: 1 2 3 4 9 10

Można umieścić dowolną liczbę Exit For instrukcji w For Each pętli.Użyto zagnieżdżone wewnątrz For Each pętli, Exit For powoduje wykonanie exit znajdujące się najniżej sterowania pętli i transfery, aby następny wyższy poziom zagnieżdżenia.

Exit Forczęsto jest używany po przeprowadzeniu oceny pewnych warunków, na przykład w If...Then...Else struktury.Być może chcesz użyć Exit For w następujących warunkach:

  • Chwili jest niemożliwe lub niepotrzebne.Może to być spowodowane Błędna wartość lub żądanie przerwania.

  • Wyjątek wpadł w Try...Catch...Finally.Można użyć Exit For na koniec Finally bloku.

  • Tam nieskończonej pętli, czyli pętlę, która może uruchomić dużych lub nawet nieskończoną liczbę razy.Jeśli wykryje taki warunek, można użyć Exit For Aby uniknąć pętli.Aby uzyskać więcej informacji, zobacz Do...Loop — Instrukcja (Visual Basic).

Iteratory

Możesz użyć sterująca do wykonywania niestandardowych iteracji w kolekcji.Iterację może być funkcją lub Get metoda dostępu.Używa Yield instrukcja zwraca każdy element w kolekcji, jeden na raz.

Wywołujemy iterację za pomocą For Each...Next instrukcji.Każda iteracja For Each pętli wywołuje sterująca.Gdy Yield instrukcja zostanie osiągnięta w sterująca wyrażenie w Yield zwracana jest instrukcja i bieżącej lokalizacji w kodzie jest zachowywana.Wykonanie jest uruchamiany ponownie z tej lokalizacji w następnym razem, która jest wywoływana sterująca.

W poniższym przykładzie użyto funkcja sterująca.Funkcja sterująca ma Yield instrukcji, która znajduje się wewnątrz dla...Następny pętli.W ListEvenNumbers metod, każda iteracja For Each ciała instrukcja tworzy wywołanie funkcji sterująca, która przechodzi do następnego Yield instrukcji.

Public Sub ListEvenNumbers()
    For Each number As Integer In EvenSequence(5, 18)
        Debug.Write(number & " ")
    Next
    Debug.WriteLine("")
    ' Output: 6 8 10 12 14 16 18 
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 = firstNumber To lastNumber
        If number Mod 2 = 0 Then
            Yield number
        End If 
    Next 
End Function

Aby uzyskać więcej informacji, zobacz Iteratory (C# i Visual Basic), Yield — Instrukcja (Visual Basic) i Iterator (Visual Basic).

Techniczna realizacja

When a For Each…Next instrukcja jest uruchamiana, języka Visual Basic daje w wyniku kolekcji tylko jeden raz, przed jej uruchomienia.Jeśli zmieni się Twój blok instrukcji element lub group, te zmiany nie wpływają na iteracji pętli.

Kiedy wszystkie elementy w kolekcji kolejno przypisane do element, For Each w pętli zatrzymuje się i kontrola przechodzi do następujących instrukcji Next instrukcji.

Jeśli element nie była zadeklarowana poza pętlę, należy ją zadeklarować w For Each instrukcji.Można zadeklarować typ element jawnie przy użyciu As instrukcji, lub może polegać na wnioskowanie do przypisywane jako zamówienie typu.W obu przypadkach zakres element jest organem pętli.Jednak nie można zadeklarować element zarówno na zewnątrz i wewnątrz pętli.

Opcjonalnie można określić element w Next instrukcji.Zwiększa to czytelność tego programu, zwłaszcza, jeśli posiadać zagnieżdżonych For Each pętli.Należy określić tę samą zmienną jako ten, który pojawia się w odpowiednim For Each instrukcji.

Należy unikać, zmiana wartości element wewnątrz pętli.Ten sposób można utrudnić do odczytywania i debugowania kodu.Zmiana wartości group nie ma wpływu na kolekcję lub jego elementów, które zostały określone podczas pierwszego wprowadzania pętli.

Kiedy jesteś zagnieżdżanie pętli, jeśli Next napotkania instrukcji zewnętrznym poziomie zagnieżdżenia przed Next o poziomie wewnętrznym, kompilator sygnalizuje błąd.Jednakże kompilator może wykryć to nakładających się błąd, tylko, jeśli określisz element w każdym Next instrukcji.

Jeśli Twój kod zależy od tego, przechodzenie przez kolekcję w określonej kolejności, For Each...Next pętli nie jest najlepszym wyborem, jeśli nie znasz cechy obiektu numeratora ujawnia kolekcji.Kolejność przechodzenia nie jest określana przez program Visual Basic, ale MoveNext metody obiektu numeratora.W związku z tym, nie można przewidzieć, który z elementów kolekcji jest pierwszym, który będą zwracane w element, albo znajdował się dalej, aby być zwrócone po danego elementu.Być może osiągnąć najlepsze wyniki przy użyciu struktury różnych pętli, takich jak For...Next or Do...Loop.

Typem danych element musi być taka, że typ danych elementów group mogą być konwertowane do niego.

Typem danych group musi być typem odwołania, który odnosi się do kolekcji lub tablicę, która jest agreguje ustalony.Zazwyczaj oznacza to, że group odnosi się do obiektu, który implementuje IEnumerable interfejsu System.Collections obszaru nazw lub IEnumerable interfejsu System.Collections.Generic obszaru nazw.System.Collections.IEnumerabledefiniuje GetEnumerator metoda, która zwraca obiekt enumerator dla kolekcji.Implementuje obiektu numeratora System.Collections.IEnumerator interfejsu System.Collections obszaru nazw i udostępnia Current właściwość i Reset i MoveNext metody.Visual Basic zawsze używa tych przechodzenia kolekcji.

Konwersji zawężającej

Gdy Option Strict jest ustawiona na On, konwersji zawężającej zwykle powodują błędy kompilatora.W For Each instrukcji, jednak podczas konwersji z elementów w group do element są przeliczane i wykonywane w czasie wykonywania, a błędy kompilatora, spowodowane przez zwężenie konwersje będą pomijane.

W poniższym przykładzie, przypisanie m jako wartość początkowa dla n nie chce się skompilować przy Option Strict jest na, ponieważ zmiany przeznaczenia Long do Integer jest konwersji zawężającej.W For Each instrukcji, jednak żaden błąd kompilatora jest zgłaszane, mimo że przypisanie do number wymaga tego samego konwersja z Long do Integer.W For Each występuje błąd w czasie wykonywania instrukcja, która zawiera dużą liczbę, gdy ToInteger jest stosowany do wielu.

Option Strict On 

Module Module1
    Sub Main()
        ' The assignment of m to n causes a compiler error when  
        ' Option Strict is on. 
        Dim m As Long = 987
        'Dim n As Integer = m 

        ' The For Each loop requires the same conversion but 
        ' causes no errors, even when Option Strict is on. 
        For Each number As Integer In New Long() {45, 3, 987}
            Console.Write(number & " ")
        Next
        Console.WriteLine()
        ' Output: 45 3 987 

        ' Here a run-time error is raised because 9876543210 
        ' is too large for type Integer. 
        'For Each number As Integer In New Long() {45, 3, 9876543210} 
        '    Console.Write(number & " ") 
        'Next

        Console.ReadKey()
    End Sub 
End Module

IEnumerator wywołań

Podczas realizacji For Each...Next rozpoczyna pętlę, języka Visual Basic weryfikuje, że group odnosi się do obiektu kolekcji prawidłowy.W przeciwnym razie to zgłasza wyjątek.W przeciwnym razie wywołuje MoveNext metoda a Current właściwość obiektu numeratora, aby powrócić do pierwszego elementu.Jeśli MoveNext wskazuje, że nie jest Brak następnego elementu, oznacza to, jeśli kolekcja jest pusta, For Each w pętli zatrzymuje się i kontrola przechodzi do następujących instrukcji Next instrukcji.W przeciwnym razie ustawia języka Visual Basic element do pierwszego elementu i działa bloku instrukcji.

Za każdym razem spotkania języka Visual Basic Next instrukcji, powraca na For Each instrukcji.Ponownie wywołuje MoveNext i Current zwraca następny element i ponownie uruchamia bloku lub pętlę w zależności od wyniku.Ten proces jest kontynuowany aż do MoveNext wskazuje, że nie istnieje żaden następny element lub Exit For napotkania instrukcji.

Modyfikowanie kolekcji. Moduł wyliczający obiekt zwrócony przez GetEnumerator normalnie nie jest już możliwe zmienianie zbioru przez dodawanie, usuwanie, zastępowanie lub zmiana kolejności żadnych elementów.Jeśli zmienisz kolekcja po zainicjowaniu For Each...Next pętli, obiektu numeratora staje się nieważna i powoduje, że następna próba uzyskania dostępu do elementu InvalidOperationException wyjątku.

Jednak to blokowanie modyfikacji nie jest ustalona przez Visual Basic, ale raczej przez wprowadzenie w życie IEnumerable interfejsu.Istnieje możliwość wdrożenia IEnumerable w sposób, który pozwala na modyfikację podczas iteracji.Jeśli zastanawiasz się robi takich dynamicznych zmian, upewnij się, że rozumiesz właściwości IEnumerable wykonania w sprawie kolekcji, którego używasz.

Modyfikacja elementów kolekcji.Current Właściwość obiektu numeratora jest ReadOnly (Visual Basic), i zwraca lokalną kopię każdego elementu w kolekcji.Oznacza to, że nie można modyfikować ze sobą elementy w For Each...Next loop.Wszelkie zmiany wprowadzone dotyczy tylko kopia lokalna z Current i nie zostanie wprowadzona do kolekcja podstawowej.Jednakże jeśli element jest typem odwołania, można zmodyfikować członkowie instancji, na które wskazuje.Poniższy przykład modyfikuje BackColor z każdej strony thisControl element.Nie można jednak modyfikować thisControl się.

Sub lightBlueBackground(ByVal thisForm As System.Windows.Forms.Form)
    For Each thisControl As System.Windows.Forms.Control In thisForm.Controls
        thisControl.BackColor = System.Drawing.Color.LightBlue
    Next thisControl
End Sub

Można zmodyfikować w poprzednim przykładzie BackColor z każdej strony thisControl element, chociaż nie można modyfikować thisControl się.

Przechodzenie przez tablice. Ponieważ Array klasy implementuje IEnumerable wystawiać wszystkie tablice interfejs, GetEnumerator metoda.Oznacza to, że można wykonać iterację tablicę z For Each...Next loop.Jednakże mogą tylko odczytywać elementy tablicy.Nie można ich zmienić.

Przykład

Poniższy przykład wyświetla wszystkie foldery w katalogu C:\ za pomocą DirectoryInfo klasy.

Dim dInfo As New System.IO.DirectoryInfo("c:\")
For Each dir As System.IO.DirectoryInfo In dInfo.GetDirectories()
    Debug.WriteLine(dir.Name)
Next

Poniżej przedstawiono przykładową procedurę sortowanie zbioru.Przykład sortuje wystąpienia Car klasy, które są przechowywane w List.Car Klasy implementuje IComparable interfejs, który wymaga, aby CompareTo metoda być wprowadzany w życie.

Każde wywołanie CompareTo metoda sprawia, że pojedynczy porównanie, w którym jest używane do sortowania.Kod napisany przez użytkownika w CompareTo metoda zwraca wartość dla każde porównanie bieżącego obiektu z innym obiektem.Wartość zwracana jest mniejsza niż zero, jeśli bieżący obiekt ma mniej niż inne obiektu, większa od zera, jeśli bieżący obiekt jest większa niż drugi obiekt i zero jeśli są równe.Dzięki temu można zdefiniować w kodzie kryteria większe niż, mniej niż, a są równe.

W ListCars metodę, cars.Sort() instrukcja sortuje listy.To wywołanie do Sort metoda List powoduje, że CompareTo metodę wywoływaną automatycznie dla Car obiektów w List.

Public Sub ListCars()

    ' Create some new cars. 
    Dim cars As New List(Of Car) From
    {
        New Car With {.Name = "car1", .Color = "blue", .Speed = 20},
        New Car With {.Name = "car2", .Color = "red", .Speed = 50},
        New Car With {.Name = "car3", .Color = "green", .Speed = 10},
        New Car With {.Name = "car4", .Color = "blue", .Speed = 50},
        New Car With {.Name = "car5", .Color = "blue", .Speed = 30},
        New Car With {.Name = "car6", .Color = "red", .Speed = 60},
        New Car With {.Name = "car7", .Color = "green", .Speed = 50}
    }

    ' Sort the cars by color alphabetically, and then by speed 
    ' in descending order.
    cars.Sort()

    ' View all of the cars. 
    For Each thisCar As Car In cars
        Debug.Write(thisCar.Color.PadRight(5) & " ")
        Debug.Write(thisCar.Speed.ToString & " ")
        Debug.Write(thisCar.Name)
        Debug.WriteLine("")
    Next 

    ' Output: 
    '  blue  50 car4 
    '  blue  30 car5 
    '  blue  20 car1 
    '  green 50 car7 
    '  green 10 car3 
    '  red   60 car6 
    '  red   50 car2 
End Sub 

Public Class Car
    Implements IComparable(Of Car)

    Public Property Name As String 
    Public Property Speed As Integer 
    Public Property Color As String 

    Public Function CompareTo(ByVal other As Car) As Integer _
        Implements System.IComparable(Of Car).CompareTo
        ' A call to this method makes a single comparison that is 
        ' used for sorting. 

        ' Determine the relative order of the objects being compared. 
        ' Sort by color alphabetically, and then by speed in 
        ' descending order. 

        ' Compare the colors. 
        Dim compare As Integer
        compare = String.Compare(Me.Color, other.Color, True)

        ' If the colors are the same, compare the speeds. 
        If compare = 0 Then
            compare = Me.Speed.CompareTo(other.Speed)

            ' Use descending order for speed.
            compare = -compare
        End If 

        Return compare
    End Function 
End Class

Zobacz też

Informacje

For...Next — Instrukcja (Visual Basic)

While...End While — Instrukcja (Visual Basic)

Do...Loop — Instrukcja (Visual Basic)

Koncepcje

Struktury pętli (Visual Basic)

Rozszerzanie i zwężanie konwersji (Visual Basic)

Inicjatory obiektów: typy nazwane i anonimowe (Visual Basic)

Inicjatory kolekcji (Visual Basic)

Inne zasoby

Kolekcje (C# i Visual Basic)

Tablice w Visual Basic