For Each...Next Deyimi (Visual Basic)

Bir koleksiyondaki her öğe için bir deyim grubunu yineler.

Syntax

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

Bölümler

Süre Tanım
element For Eachİfadesinde gereklidir. NextDeyimde isteğe bağlı. Değişken. Koleksiyonun öğeleri arasında yineleme yapmak için kullanılır.
datatype Açık ise Option Infer (varsayılan) veya zaten bildirilirse, isteğe bağlıdır element ; Option Infer kapalıysa ve önceden bildirilmemiş olması gerekir element . Veri türü element .
group Gereklidir. Bir koleksiyon türü veya nesne olan türü olan bir değişken. Tekrarlanması gereken koleksiyona başvurur statements .
statements İsteğe bağlı. For Each Next İçindeki ve içindeki her öğe için çalışan arasında bir veya daha fazla deyim group .
Continue For İsteğe bağlı. Denetimi döngünün başlangıcına aktarır For Each .
Exit For İsteğe bağlı. Denetimi döngünün dışına aktarır For Each .
Next Gereklidir. Döngünün tanımını sonlandırır For Each .

Basit örnek

Bir For Each Next koleksiyonun veya dizinin her öğesi için bir deyim kümesini yinelemek istediğinizde bir... döngüsü kullanın.

İpucu

İçin A... Sonraki Ifade , bir döngünün her yinelemesini bir denetim değişkeniyle ilişkilendirebileceğiniz ve değişkenin ilk ve son değerlerini belirleyebileceğiniz zaman iyi şekilde kullanılır. Bununla birlikte, bir koleksiyonla ilgilendiğinizde, ilk ve son değer kavramı anlamlı değildir ve koleksiyonun kaç öğe olduğunu bilmeniz gerekmez. Bu tür bir durumda,... For Each Next döngüsü genellikle daha iyi bir seçimdir.

Aşağıdaki örnekte, For Each ...Next ifade, bir liste koleksiyonunun tüm öğeleri boyunca yinelenir.

' 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

Daha fazla örnek için bkz. koleksiyonlar ve diziler.

İç içe döngüler

Bir For Each döngüyü diğerinin içine yerleştirerek döngüleri iç içe geçirebilirsiniz.

Aşağıdaki örnek iç içe geçmiş For Each ...Next yapıları.

' 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

Döngüleri iç içe aktardığınızda her döngünün benzersiz bir element değişkeni olmalıdır.

Ayrıca, farklı türlerde denetim yapılarını birbirleriyle iç içe geçirebilirsiniz. Daha fazla bilgi için bkz. Iç Içe denetim yapıları.

İçin çık ve devam et

Exit for deyimleri yürütmenin uygulamadan çıkmasına neden olur For ...Next öğesini Loop ve deyimden sonraki deyime aktarır Next .

Continue Forİfade, denetimi döngünün bir sonraki yinelemesine hemen aktarır. Daha fazla bilgi için bkz. Continue bildirisi.

Aşağıdaki örnek, ve deyimlerinin nasıl kullanılacağını göstermektedir Continue For Exit For .

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 8, 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

Exit ForBir döngüye herhangi bir sayıda deyim yerleştirebilirsiniz For Each . İç içe döngüler içinde kullanıldığında For Each Exit For yürütmenin en içteki döngüden çıkmasına ve denetimi bir sonraki daha yüksek iç içe geçme düzeyine aktarmasına neden olur.

Exit For genellikle bir koşul değerlendirmesinden sonra, örneğin bir If .. Then . ...Else yapısı. Exit ForAşağıdaki koşullar için kullanmak isteyebilirsiniz:

  • Tekrarlamaya devam etmek gereksiz veya imkansız. Bunun nedeni hatalı bir değer veya sonlandırma isteği olabilir.

  • Bir özel durum içinde yakalandı Try .. Catch . ...Finally. Exit For Bloğunun sonunda kullanabilirsiniz Finally .

  • Sonsuz bir döngü vardır. Bu bir döngü, büyük veya hatta sonsuz bir sayı çalıştırabilir. Böyle bir koşulu tespit ediyorsanız, Exit For döngüyü atlamak için kullanabilirsiniz. Daha fazla bilgi için bkz . do... Loop deyimleri.

Yineleyiciler

Bir koleksiyon üzerinde özel bir yineleme gerçekleştirmek için bir Yineleyici kullanırsınız. Yineleyici bir işlev veya Get erişimci olabilir. YieldTek seferde koleksiyonun her bir öğesini döndürmek için bir ifade kullanır.

Bir ifadeyi kullanarak bir yineleyici çağırın For Each...Next . Döngünün her yinelemesi For Each yineleyiciyi çağırır. YieldYineleyiciden bir ifadeye ulaşıldığında, Yield deyimdeki ifade döndürülür ve koddaki geçerli konum korunur. Bu konumdan, yineleyici bir sonraki sefer çağrıldığında yürütme yeniden başlatılır.

Aşağıdaki örnek bir yineleyici işlevi kullanır. Yineleyici işlevinin, Yield için içindeki bir ifade vardır ... Sonraki döngü. ListEvenNumbersYönteminde, For Each ifade gövdesinin her yinelemesi bir sonraki ifadeye devam eden Yineleyici işlevine bir çağrı oluşturur Yield .

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

Daha fazla bilgi için bkz. yineleyiciler, yield ekstresive Yineleyici.

Teknik Uygulama

Bir... For Each``Next deyimin çalışması Visual Basic, döngü başlamadan önce koleksiyonu yalnızca bir kez değerlendirir. Deyiminiz değişiklikleri veya değişiklik engelleriyorsa element group , bu değişiklikler döngünün yinelemesini etkilemez.

Koleksiyondaki tüm öğeler üzerinde kapsamlı olarak atandığında element , For Each döngü duraklar ve deyimden sonraki deyime geçer Next .

seçenek çıkarımı açık ise (varsayılan ayarı) Visual Basic derleyici, veri türünü çıkarsalabilir element . Kapalıysa ve element döngü dışında bildirilmediyse, bunu bildiriminde bildirmeniz gerekir For Each . Açıkça veri türünü bildirmek için element bir As yan tümce kullanın. Öğe veri türü For Each ... yapı dışında tanımlanmamışsa Next , kapsamı döngünün gövdesidir. elementDöngüsünün dışında ve içinde bildiremezsiniz.

İsteğe bağlı olarak element Next deyimde belirtebilirsiniz. Bu, özellikle iç içe döngüler varsa programınızın okunabilirliğini geliştirir For Each . Karşılık gelen ifadede görünen değişkenle aynı değişkeni belirtmeniz gerekir For Each .

Bir döngünün içindeki değerini değiştirmeyi önlemek isteyebilirsiniz element . Bunu yapmak, kodunuzun okunmasını ve hata ayıklamasını daha zor hale getirir. Değerini değiştirmek group , döngü ilk kez girildiğinde belirlenen koleksiyonu veya öğelerini etkilemez.

Döngüleri iç içe aktardığınızda, Next iç düzeyden önce bir dış iç içe düzeyi ifadesine karşılaşılırsa Next , derleyici bir hata bildirir. Ancak, derleyici bu çakışan hatayı yalnızca her ifadede belirtirseniz tespit edebilir element Next .

Kodunuz belirli bir sırada bir koleksiyonun geçiş yöntemine bağımlıysa, For Each Next koleksiyonun sunduğu Numaralandırıcı nesnesinin özelliklerini bilmiyorsanız,... Loop en iyi seçim değildir. çapraz geçiş sırası Visual Basic, ancak MoveNext numaralandırıcı nesnesinin yöntemine göre belirlenir. Bu nedenle, koleksiyonda hangi öğenin döndürüleceğini element veya belirli bir öğeden sonra döndürülecek bir sonraki olduğunu tahmin edemeyebilirsiniz. For... Next Veya Do .. Loop . gibi farklı bir döngü yapısı kullanarak daha güvenilir sonuçlar elde edebilirsiniz.

Çalışma zamanının içindeki öğeleri ' a dönüştürebilmelidir group element . [ Option Strict ] İfadesinde, hem genişletme hem de daraltma dönüştürmelerine izin verilip verilmeyeceğini ( Option Strict kapalı, varsayılan değeri) veya yalnızca genişletme dönüştürmelerine izin verilip verilmeyeceğini ( Option Strict açık olduğunu) denetler. Daha fazla bilgi için bkz. daraltma dönüştürmeleri.

Veri türü, group bir koleksiyona veya Numaralandırılabilir bir diziye başvuran bir başvuru türü olmalıdır. En yaygın olarak bu group IEnumerable , System.Collections ad alanının arabirimini veya IEnumerable<T> System.Collections.Generic ad alanının arabirimini uygulayan bir nesneye başvurur. System.Collections.IEnumerableGetEnumeratorkoleksiyon için bir Numaralandırıcı nesnesi döndüren yöntemini tanımlar. Numaralandırıcı nesnesi System.Collections.IEnumerator System.Collections ad alanı arabirimini uygular ve Current özelliğini ve Reset ve MoveNext yöntemlerini gösterir. Visual Basic, koleksiyonu çapraz geçirmek için bunları kullanır.

Daraltma dönüştürmeleri

Ne zaman Option Strict ayarlandığında On , daraltma dönüştürmeleri normalde derleyici hatalarına neden olur. Ancak, ' For Each deki öğelerinden dönüşümler, group çalışma zamanında element değerlendirilir ve gerçekleştirilir ve daraltma dönüştürmelerinden kaynaklanan derleyici hataları bastırılır.

Aşağıdaki örnekte, ' m n Option Strict a ' a dönüştürme bir Long daraltma dönüştürmesi olduğundan, için başlangıç değeri olarak atama, tarihinde derleme yapmaz Integer . Ancak,, öğesine atama, ' den ' e For Each number aynı dönüştürmeyi gerektirse de, hiçbir derleyici hatası raporlanır Long Integer . For EachBüyük bir sayı içeren ifadede, büyük sayıya uygulandığında bir çalışma zamanı hatası oluşur ToInteger .

Option Strict On

Imports System

Module Program
    Sub Main(args As String())
        ' 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
    End Sub
End Module

IEnumerator çağrıları

bir For Each ... Next döngüsünün yürütülmesi başladığında, group geçerli bir koleksiyon nesnesine başvuran Visual Basic doğrular. Aksi takdirde, bir özel durum oluşturur. Aksi takdirde, MoveNext Current ilk öğeyi döndürmek için yöntemini ve Numaralandırıcı nesnesinin özelliğini çağırır. Eğer MoveNext bir sonraki öğe olmadığını gösteriyorsa, diğer bir deyişle, koleksiyon boşsa, For Each döngü duraklar ve denetimi deyimden sonraki ifadeye geçirir Next . aksi takdirde, Visual Basic element ilk öğesine ayarlar ve ekstre bloğunu çalıştırır.

her Visual Basic Next deyimle karşılaştığında, ifadeye geri döner For Each . Yeniden çağırır MoveNext ve bir Current sonraki öğesini döndürür ve sonra da bloğu çalıştırır veya sonuca bağlı olarak döngüyü sonlandırır. Bu işlem MoveNext , bir sonraki öğe veya bir deyimin karşılaştığı anlamına gelene kadar devam eder Exit For .

Koleksiyonu değiştirme. Normal olarak döndürülen Numaralandırıcı nesnesi GetEnumerator herhangi bir öğeyi ekleyerek, silerek, değiştirerek veya yeniden sıralayarak koleksiyonu değiştirmenize izin vermez. For Each... Döngüsünü başlattıktan sonra koleksiyonu değiştirirseniz Next , Numaralandırıcı nesnesi geçersiz hale gelir ve bir sonraki erişim denemesi InvalidOperationException özel duruma neden olur.

ancak, bu değişikliğin engellenmesi Visual Basic tarafından belirlenir, ancak bunun yerine IEnumerable arabirimin uygulanması. IEnumerableYineleme sırasında değişikliklere izin veren bir şekilde uygulanması mümkündür. Bu tür dinamik değişikliği yapmayı düşünüyorsanız, kullanmakta olduğunuz koleksiyonda uygulamanın özelliklerini anladığınızdan emin olun IEnumerable .

Koleksiyon öğelerini değiştirme. CurrentNumaralandırıcı nesnesinin özelliği salt okunurve her koleksiyon öğesinin yerel bir kopyasını döndürür. Bu, öğeleri bir For Each ... döngüsünde değiştiremeyeceğiniz anlamına gelir Next . Yaptığınız herhangi bir değişiklik yalnızca yerel kopyayı etkiler Current ve temel koleksiyona geri yansıtılmaz. Ancak, bir öğe bir başvuru türü ise, gösterdiği örnek üyelerini değiştirebilirsiniz. Aşağıdaki örnek BackColor her bir öğenin üyesini değiştirir thisControl . Ancak, thisControl kendisini değiştiremezsiniz.

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

Önceki örnek, BackColor thisControl kendisini değiştiremese de, her öğenin üyesini değiştirebilir thisControl .

Dizileri geçme. ArraySınıfı IEnumerable arabirimini uyguladığından, tüm diziler yöntemini kullanıma sunar GetEnumerator . Bu,... döngüsü ile bir dizi içinde yineleyebilir For Each Next . Ancak, yalnızca dizi öğelerini okuyabilirsiniz. Bunları değiştiremezsiniz.

Örnek 1

Aşağıdaki örnek, C:\ içindeki tüm klasörleri listeler. sınıfını kullanarak Dizin DirectoryInfo .

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

Örnek 2

Aşağıdaki örnek bir koleksiyonu sıralamak için bir yordam gösterir. Örnek, Car içinde depolanan bir sınıfın örneklerini sıralar List<T> . CarSınıfı, IComparable<T> yönteminin uygulanması için arabirimini uygular CompareTo .

Yöntemine yapılan her çağrı, CompareTo sıralama için kullanılan tek bir karşılaştırma yapar. Yöntemdeki Kullanıcı tarafından yazılan kod, CompareTo geçerli nesnenin her bir karşılaştırması için başka bir nesneyle ilgili bir değer döndürür. Geçerli nesne diğer nesneden daha küçükse döndürülen değer sıfırdan küçük, geçerli nesne diğer nesneden büyükse sıfırdan büyük ve eşitse sıfır. Bu, büyük, küçüktür ve eşittir ölçütlerine göre kod içinde tanımlamanızı sağlar.

Yönteminde, ListCars cars.Sort() ifade listeyi sıralar. Öğesinin yöntemine yapılan bu çağrı, Sort List<T> CompareTo yönteminin içindeki nesneler için otomatik olarak çağrılmasına neden olur Car 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

Ayrıca bkz.