For Each...Next Deyimi (Visual Basic)

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

Sözdizimi

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

Parça

Süre Tanım
element Deyiminde For Each gereklidir. deyiminde Next isteğe bağlı. Değişken. Koleksiyonun öğeleri arasında yineleme yapmak için kullanılır.
datatype İsteğe bağlı ise Option Infer (varsayılan) veya element zaten bildirildiyse; kapalıysa ve element zaten bildirlenmemişse Option Infer gereklidir. veri türü element.
group Gerekli. Koleksiyon türü veya Nesne türüne sahip bir değişken. Üzerinde statements tekrarlanacak olan koleksiyonu ifade eder.
statements isteğe bağlı. ile arasında For Each bulunan ve Next içindeki her öğe groupüzerinde çalışan bir veya daha fazla deyim.
Continue For isteğe bağlı. Denetimi döngünün başlangıcına For Each aktarır.
Exit For isteğe bağlı. Aktarımlar denetimi döngünün For Each dışına aktarır.
Next Gerekli. Döngünün For Each tanımını sonlandırır.

Basit Örnek

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

İpucu

A For... Bir döngünün her yinelemesini bir denetim değişkeniyle ilişkilendirip bu değişkenin ilk ve son değerlerini belirleyebildiğiniz durumlarda Next Deyimi iyi çalışır. Ancak, bir koleksiyonla ilgilenirken, ilk ve son değerler kavramı anlamlı değildir ve koleksiyonun kaç öğeye sahip olduğunu bilmeniz gerekmez. Bu tür bir durumda, bir For Each...Next döngüsü genellikle daha iyi bir seçimdir.

Aşağıdaki örnekte, For Each...Next deyimi, List koleksiyonunun tüm öğelerinde 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.

İç İçe Döngüler

Bir döngünün içine başka bir döngü koyarak döngüleri iç içe For Each yerleştirebilirsiniz.

Aşağıdaki örnekte iç içe yerleştirilmiş For Each...Next Yapı.

' 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 yerleştirdiğinizde, her döngünün benzersiz element bir değişkeni olmalıdır.

Ayrıca, farklı türlerde denetim yapılarını da iç içe yerleştirebilirsiniz. Daha fazla bilgi için bkz . İç İçe Denetim Yapıları.

Için Çıkış ve Devam Et

Exit For deyimi yürütmenin For...Next döngüsü ve denetimi deyimini izleyen deyime Next aktarır.

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

Aşağıdaki örnekte ve Exit For deyimlerinin nasıl kullanılacağı Continue For gösterilmektedir.

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

Döngüye For Each istediğiniz sayıda Exit For deyim ekleyebilirsiniz. İç içe For Each döngüler içinde kullanıldığında, Exit For yürütmenin en içteki döngüden çıkmasına neden olur ve denetimi bir sonraki üst iç içe yerleştirme düzeyine aktarır.

Exit For genellikle bazı koşullar değerlendirildikten sonra kullanılır, örneğin bir If...Then...Else Yapısı. Aşağıdaki koşullar için kullanmak Exit For isteyebilirsiniz:

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

  • Özel durum Trybir ...Catch...Finally. Bloğun sonunda Finally kullanabilirsinizExit For.

  • Sonsuz bir döngü vardır ve bu döngü çok sayıda hatta sonsuz sayıda çalıştırabilen bir döngüdür. Böyle bir koşul algılarsanız, döngüden kaçmak için kullanabilirsiniz Exit For . Daha fazla bilgi için bkz . Do... Döngü Deyimi.

Yineleyiciler

Bir koleksiyon üzerinde özel yineleme gerçekleştirmek için yineleyici kullanırsınız. Yineleyici bir işlev veya Get erişimci olabilir. Koleksiyonun her öğesini birer birer döndürmek için bir Yield deyimini kullanır.

Deyimini kullanarak yineleyici çağırırsınız For Each...Next . Döngünün For Each her yinelemesi yineleyiciyi çağırır. Yineleyicide bir Yield deyime ulaşıldığında, deyimindeki Yield ifade döndürülür ve koddaki geçerli konum korunur. Yineleyici bir sonraki çağrılışında yürütme bu konumdan yeniden başlatılır.

Aşağıdaki örnekte yineleyici işlevi kullanılır. Yineleyici işlevinin for... içinde bir deyimi vardırYield. Sonraki döngü. yönteminde ListEvenNumbers , deyim gövdesinin For Each her yinelemesi, bir sonraki Yield deyime devam eden yineleyici işlevine bir çağrı oluşturur.

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, Verim Deyimi ve Yineleyici.

Teknik Uygulama

For EachBir ...Next deyimi çalıştırılır, Visual Basic döngü başlamadan önce koleksiyonu yalnızca bir kez değerlendirir. Deyiminiz veya değişikliklerini elementgroupengellerse, bu değişiklikler döngünün yinelenmesini etkilemez.

Koleksiyondaki tüm öğeler ardışık olarak öğesine atandığında elementFor Each döngü durdurulur ve denetim deyimini izleyen deyimine Next geçer.

Option Infer açıksa (varsayılan ayarı), Visual Basic derleyicisi elementveri türünü çıkarsayabilir. Kapalıysa ve element döngü dışında bildirilmemişse, deyiminde For Each bildirmeniz gerekir. Veri türünü element açıkça bildirmek için bir As yan tümcesi kullanın. Öğenin veri türü ...Next yapısının For Eachdışında tanımlanmadığı sürece, kapsamı döngünün gövdesidir. Döngünün hem dışında hem de içinde bildirimde element bulunamayacağınızı unutmayın.

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

Bir döngünün içindeki değerini element değiştirmekten kaçınmak isteyebilirsiniz. Bunu yapmak kodunuzun okunmasını ve hatalarını ayıklamayı zorlaştırabilir. değerinin group değiştirilmesi, döngüye ilk girildiğinde belirlenen koleksiyonu veya öğelerini etkilemez.

Döngüleri iç içe yerleştirdiğinizde, iç Next düzeyin önünde dış iç içe bir düzeyin Next deyimiyle karşılaşılırsa, derleyici bir hata sinyali gönderir. Ancak, derleyici bu çakışan hatayı yalnızca her Next deyimde belirtirseniz element algılayabilir.

Kodunuz bir koleksiyonu belirli bir sırada geçirmeye bağımlıysa, For Eachkoleksiyonun kullanıma sunmadığı numaralandırıcı nesnesinin özelliklerini bilmiyorsanız...Next döngüsü en iyi seçenek değildir. Geçiş sırası Visual Basic tarafından değil, MoveNext numaralandırıcı nesnesinin yöntemiyle belirlenir. Bu nedenle, koleksiyonun hangi öğesinin içinde elementdöndürülecek ilk öğe olduğunu veya belirli bir öğeden sonra hangi öğenin döndürüleceğini tahmin edemeyebilirsiniz. ...Next veya Do.Loop..gibi Forfarklı bir döngü yapısı kullanarak daha güvenilir sonuçlar elde edebilirsiniz.

Çalışma zamanının içindeki groupelementöğelerini öğesine dönüştürebilmesi gerekir. [Option Strict] deyimi, genişletme ve 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) denetler. Daha fazla bilgi için bkz . Dönüştürmeleri daraltma.

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 ad alanının arabirimini veya ad alanının arabirimini System.Collections uygulayan IEnumerable bir nesneye IEnumerable<T> başvururSystem.Collections.Generic. System.Collections.IEnumerableGetEnumerator, koleksiyon için bir numaralandırıcı nesnesi döndüren yöntemini tanımlar. Numaralandırıcı nesnesi ad alanının arabirimini uygular System.Collections.IEnumerator ve özelliği ile Reset ve MoveNext yöntemlerini kullanıma sunarCurrent.System.Collections Visual Basic bunları kullanarak koleksiyonun çapraz geçişini kullanır.

Dönüştürmeleri Daraltma

olarak Option Strict ayarlandığında On, dönüştürmeleri daraltmak normalde derleyici hatalarına neden olur. Ancak bir For Each deyimde, içindeki groupelement öğelerden dönüştürmeler çalışma zamanında değerlendirilir ve gerçekleştirilir ve daraltma dönüştürmelerinin neden olduğu derleyici hataları gizlenır.

Aşağıdaki örnekte, öğesinin ilk değeri n olarak ataması m açık olduğunda Option Strict derlenemez çünkü bir'in Long bir'e dönüştürülmesi Integer bir daraltma dönüştürmesidir. Ancak deyiminde For Each , ataması number ile aynı dönüştürmeyi LongIntegergerektirse bile derleyici hatası bildirilmemiştir. For Each Büyük bir sayı içeren deyiminde, büyük sayıya uygulandığında ToInteger bir çalışma zamanı hatası oluşur.

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 ...Next döngüsü yürütülmeye For Eachbaşladığında, Visual Basic geçerli bir koleksiyon nesnesine başvuruda bulunduğunu group doğrular. Aksi takdirde, bir özel durum oluşturur. Aksi takdirde, ilk öğeyi MoveNext döndürmek için yöntemini ve Current numaralandırıcı nesnesinin özelliğini çağırır. Bir sonraki öğe olmadığını gösterirse MoveNext , yani koleksiyon boşsa döngü For Each durdurulur ve denetim deyimini izleyen deyimine Next geçer. Aksi takdirde, Visual Basic ilk öğeye ayarlar element ve deyimi bloğunu çalıştırır.

Visual Basic deyimiyle her karşılaştığında Next deyimine For Each döner. Bir sonraki öğeyi döndürmek için ve Current öğesini yeniden çağırır MoveNext ve yine sonucuna bağlı olarak bloğu çalıştırır veya döngünün durdurulur. Bu işlem, bir sonraki öğe olmadığını veya bir deyimle karşılaşıldığını belirtene Exit For kadar MoveNext devam eder.

Koleksiyonu değiştirme. tarafından GetEnumerator döndürülen numaralandırıcı nesnesi normalde öğeleri ekleyerek, silerek, değiştirerek veya yeniden sıralayarak koleksiyonu değiştirmenize izin vermez. Bir For Each...Next döngüsü başlattıktan sonra koleksiyonu değiştirirseniz, numaralandırıcı nesnesi geçersiz hale gelir ve bir sonraki öğeye erişme girişimi bir InvalidOperationException özel duruma neden olur.

Ancak, bu değişikliğin engellenmesi Visual Basic tarafından değil, arabirimin uygulanması tarafından IEnumerable belirlenir. Yineleme sırasında değişikliğe izin veren bir şekilde uygulamak IEnumerable mümkündür. Böyle bir dinamik değişiklik yapmayı düşünüyorsanız, kullandığınız koleksiyondaki uygulamanın özelliklerini IEnumerable anladığınızdan emin olun.

Koleksiyon Öğelerini Değiştirme. Current Numaralandırıcı nesnesinin özelliği ReadOnly'dir ve her koleksiyon öğesinin yerel bir kopyasını döndürür. Bu, öğeleri bir ...Next döngüsünde For Eachdeğiştiremeyeceğiniz anlamına gelir. Yaptığınız değişiklikler yalnızca yerel kopyayı Current etkiler ve temel alınan koleksiyona geri yansıtılamaz. Ancak, bir öğe bir başvuru türüyse, işaret ettiği örneğin üyelerini değiştirebilirsiniz. Aşağıdaki örnek, her thisControl öğenin üyesini değiştirirBackColor. Ancak, kendisini değiştiremezsiniz thisControl .

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, kendisini değiştiremese BackColor de her thisControl öğenin üyesini değiştirebilir thisControl .

Dizileri Geçirme. Array sınıfı arabirimini uyguladığındanIEnumerable, tüm diziler yöntemini kullanıma sunarGetEnumerator. Bu, bir dizide ...Next döngüsüyle For Eachyineleme yapabileceğiniz anlamına gelir. Ancak, yalnızca dizi öğelerini okuyabilirsiniz. Bunları değiştiremezsiniz.

Örnek 1

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

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 örnekte bir koleksiyonu sıralama yordamı gösterilmektedir. Örnek, içinde depolanan List<T>bir Car sınıfın örneklerini sıralar. Car sınıfı, yönteminin IComparable<T> uygulanmasını gerektiren arabirimini CompareTo uygular.

yöntemine yapılan CompareTo her çağrı, sıralama için kullanılan tek bir karşılaştırma yapar. yönteminde CompareTo kullanıcı tarafından yazılan kod, geçerli nesnenin başka bir nesneyle her karşılaştırması için bir değer döndürür. Döndürülen değer, geçerli nesne diğer nesneden küçükse 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ırdan büyük olur. Bu, kodda büyüktür, küçüktür ve eşittir ölçütlerini tanımlamanızı sağlar.

yönteminde ListCarscars.Sort() deyimi listeyi sıralar. yöntemine yapılan Sort bu çağrı, yönteminin List<T>CompareTo içindeki nesneler için Car otomatik olarak çağrılmalarına Listneden olur.

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.