Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Yineleyici, listeler ve diziler gibi koleksiyonlarda adım adım ilerleyebilmek için kullanılabilir.
Yineleyici yöntemi veya get erişimcisi bir koleksiyon üzerinde özel yineleme gerçekleştirir. Yineleyici yöntemi, her öğeyi birer birer döndürmek için Yield deyimini kullanır. bir Yield deyimine ulaşıldığında koddaki geçerli konum hatırlanır. Yineleyici işlevi bir sonraki çağrılışında yürütme bu konumdan yeniden başlatılır.
Her Biri İçin…Sonraki deyimini kullanarak veya bir LINQ sorgusu kullanarak istemci kodundan bir yineleyici tüketirsiniz.
Aşağıdaki örnekte, döngünün For Each ilk yinelemesi, ilk SomeNumbers deyime ulaşılana kadar yürütmenin Yield yineleyici yönteminde ilerlemesine neden olur. Bu yineleme 3 değerini döndürür ve yineleyici yöntemindeki geçerli konum korunur. Döngünün bir sonraki yinelemesinde, yineleyici yönteminde yürütme kaldığı yerden devam eder ve bir Yield deyime ulaştığında yeniden durduruluyor. Bu yineleme 5 değerini döndürür ve yineleyici yöntemindeki geçerli konum yeniden korunur. Yineleyici yönteminin sonuna ulaşıldığında döngü tamamlanır.
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
Bir yineleyici metodunun veya get erişimcisinin dönüş türü IEnumerable, IEnumerable<T>, IEnumerator veya IEnumerator<T> olabilir.
Yinelemeyi sonlandırmak için bir Exit Function veya Return deyimi kullanabilirsiniz.
Visual Basic yineleyici işlevi veya get erişimci bildirimi bir Yineleyici değiştiricisi içerir.
Yineleyiciler Visual Studio 2012'de Visual Basic'te tanıtıldı.
Uyarı
Makaledeki, Basit Yineleyici örneği dışındaki tüm örnekler için, ve System.Collections ad alanları için System.Collections.Generic deyimlerini ekleyin.
Basit Yineleyici
Aşağıdaki örnekte, bir tek Yield deyim For...Next döngüsünün içindedir.
Main içinde, For Each deyiminin her yinelemesi, yineleyici işlevine bir çağrı oluşturur ve bunu bir sonraki Yield deyimine geçirmek için ilerler.
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
Koleksiyon Sınıfı Oluşturma
Aşağıdaki örnekte, DaysOfTheWeek sınıfı bir IEnumerable arabirimini uygular ve bu da bir GetEnumerator yöntemi gerektirir. Derleyici, bir GetEnumerator yöntemini örtük şekilde çağırır, bu da bir IEnumerator döndürür.
GetEnumerator yöntemi kullanarak her dizeyi Yield teker teker geri döndürür ve fonksiyon bildiriminde bir Iterator değiştirici bulunur.
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
Aşağıdaki örnek, bir Zoo hayvan koleksiyonu içeren bir sınıf oluşturur.
For Each ifadesi, sınıf örneğine (theZoo) başvurarak örtük olarak GetEnumerator yöntemini çağırır.
For Each ve Birds ile Mammals özelliklerine başvuran deyimler, AnimalsForType adlandırılmış yineleyici yöntemini kullanır.
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
Deneme Blokları
Visual Basic, bir Yield ifadesine Try "Try...Catch...Finally Deyimi" bloğunda izin verir.
Try deyimi içeren bir Yield blok, Catch blokları içerebilir ve bir Finally bloğu içerebilir.
Aşağıdaki örnek, yineleyici işlevinde Try, Catch ve Finally bloklarını içerir.
Finally Yineleyici işlevindeki blok, yineleme tamamlanmadan önce For Each yürütülür.
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
Yield deyimi bir Catch blok veya Finally blok içinde olamaz.
Eğer For Each gövde (yineleyici yöntem yerine) bir özel durum oluşturursa, yineleyici işlevdeki bir Catch blok yürütülmez, ancak yineleyici işlevdeki bir Finally blok yürütülür.
Catch Yineleyici işlevinin içindeki bir blok yalnızca yineleyici işlevinin içinde oluşan özel durumları yakalar.
Anonim Yöntemler
Visual Basic'te anonim bir işlev yineleyici işlevi olabilir. Aşağıdaki örnekte bu gösterilmektedir.
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()
Aşağıdaki örnek, bağımsız değişkenleri doğrulayan yineleyici olmayan bir yöntemi göstermektedir. yöntemi, koleksiyon öğelerini açıklayan anonim bir yineleyicinin sonucunu döndürür.
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
Yineleyici işlevinin içinde doğrulama varsa, gövdenin ilk yinelemesi For Each başlayana kadar doğrulama gerçekleştirilemez.
Yineleyicileri Genel Listeyle Kullanma
Aşağıdaki örnekte, Stack(Of T) genel sınıf genel arabirimini uygular IEnumerable<T> .
Push yöntemi, türündeki Tbir diziye değerler atar. yöntemi, GetEnumerator deyimini kullanarak Yield dizi değerlerini döndürür.
Genel GetEnumerator yöntemin yanı sıra, genel olmayan GetEnumerator yöntemi de uygulanmalıdır. Bunun nedeni IEnumerable<T>'nin IEnumerable'den devralıyor olmasıdır. Genel olmayan uygulama, genel uygulamaya saptır.
Örnek, aynı veri koleksiyonu aracılığıyla yinelemenin çeşitli yollarını desteklemek için adlandırılmış yineleyiciler kullanır. Bu adlandırılmış yineleyiciler TopToBottom ve BottomToTop özellikleri ile TopN yöntemidir.
Özellik bildirimi BottomToTop anahtar sözcüğünü Iterator içerir.
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
Söz Dizimi Bilgileri
Yineleyici bir yöntem veya get erişimci olarak yer alabilir. Yineleyici bir olayda, örnek oluşturucusunda, statik oluşturucuda veya statik yıkıcıda gerçekleşemez.
Deyimdeki Yield ifade türünden yineleyicinin dönüş türüne örtük dönüştürme bulunmalıdır.
Visual Basic'te bir yineleyici yöntemde ByRef parametre bulunamaz.
Visual Basic'te "Yield" ayrılmış bir sözcük değildir ve yalnızca bir Iterator yöntemi veya get erişimcisi içerisinde kullanıldığında özel bir anlam taşır.
Teknik Uygulama
Bir yineleyiciyi bir yöntem olarak yazmanıza rağmen, derleyici bunu iç içe geçmiş bir sınıfa (aslında bir durum makinesi) çevirir. Bu sınıf, istemci kodundaki döngü devam ettikçe yineleyicinin For Each...Next konumunu izler.
Derleyicinin ne yaptığını görmek için Ildasm.exe aracını kullanarak yineleyici yöntemi için oluşturulan ortak ara dil kodunu görüntüleyebilirsiniz.
Bir sınıf veya yapı için yineleyici oluşturduğunuzda arabirimin tamamını IEnumerator uygulamanız gerekmez. Derleyici yineleyiciyi algıladığında, Current veya MoveNext arabiriminin Dispose, IEnumerator, ve IEnumerator<T> yöntemlerini otomatik olarak oluşturur.
Döngünün For Each…Next her ardışık yinelemesinde (veya doğrudan çağrısında IEnumerator.MoveNext), sonraki yineleyici kod gövdesi önceki Yield deyimden sonra devam eder. Daha sonra yineleyici gövdesinin Yield sonuna ulaşılana kadar veya bir Exit Function veya Return deyimiyle karşılaşılana kadar sonraki Yield deyime devam eder.
Yineleyiciler IEnumerator.Reset yöntemini desteklemez. Baştan yeniden yinelemek için yeni bir yineleyici edinmeniz gerekir.
Ek bilgi için bkz. Visual Basic Dil Belirtimi.
Yineleyicilerin Kullanımı
Yineleyiciler, bir liste dizisini doldurmak için karmaşık kod kullanmanız gerektiğinde döngünün For Each basitliğini korumanızı sağlar. Bu, aşağıdakileri yapmak istediğinizde yararlı olabilir:
İlk
For Eachdöngü yinelemesinin ardından liste dizisini değiştirin.Döngünün ilk yinelemesinden önce büyük bir listeyi tamamen
For Eachyüklemekten kaçının. Tablo satırlarından oluşan bir toplu iş yüklemek için sayfalanmış getirme işlemi örnek olarak verilmiştir. Başka bir örnek, .NET Framework içinde yineleyiciler uygulayan yöntemidir EnumerateFiles .Liste oluşturmayı yineleyici içinde kapsülleyin. Yineleyici yönteminde, listeyi derleyebilir ve ardından her sonucu bir döngü halinde vekleyebilirsiniz.