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 Each
koleksiyonun 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
Try
bir ...Catch
...Finally
. Bloğun sonundaFinally
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 Each
Bir ...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 element
group
engellerse, bu değişiklikler döngünün yinelenmesini etkilemez.
Koleksiyondaki tüm öğeler ardışık olarak öğesine atandığında element
For Each
döngü durdurulur ve denetim deyimini izleyen deyimine Next
geçer.
Option Infer açıksa (varsayılan ayarı), Visual Basic derleyicisi element
veri 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 Each
dışı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 Each
koleksiyonun 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 element
dö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 For
farklı bir döngü yapısı kullanarak daha güvenilir sonuçlar elde edebilirsiniz.
Çalışma zamanının içindeki group
element
öğ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.IEnumerable
GetEnumerator, 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 group
element
öğ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 Long
Integer
gerektirse 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 Each
baş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 Each
değ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 Each
yineleme 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 ListCars
cars.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 List
neden 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