Soru Tarihi:
Visual Basic'teki For Each...Next ifadesi koleksiyonların veya dizilerin elemanlarını döngülemek için kullanılır. VB6'dan itibaren standart koleksiyonlarla döngüleme desteklendi, VB.NET'te ise belirli bir arabirimi uygulayan tüm türler için destek bulunmaktadır. Ancak kendi döngüleme için kullanıcı tanımlı koleksiyonlar oluşturulması gerektiğinde, gereken altyapının doğru bir şekilde uygulanması önemlidir.
Sorun
Elemanları saklamak yeterli değildir; For Each ifadeleri özel IEnumerable arabirimini desteklemeyi gerektirir. Çoğu özelleştirilmiş koleksiyon derlemesi, Add/Get yöntemi ile sınırlı kalmış, nesne "kara kutu" haline gelmiştir. Bu durum, döngü yapısına entegrasyonu engellemekte ve hatalara yol açmaktadır.
Çözüm
For Each'in koleksiyonunuzla doğru bir şekilde çalışabilmesi için IEnumerable arabiriminin uygulanması ve tipli elemanlarla çalışmak için IEnumerable(Of T) desteğinin sağlanması gerekmektedir. Ayrıca, IEnumerator arabirimini (veya generic versiyonlarda IEnumerator(Of T)yi) uygulayan kendi enumeratörünüzü oluşturmalısınız.
Örnek:
Public Class IntCollection Implements IEnumerable(Of Integer) Private ReadOnly items As New List(Of Integer)() Public Sub Add(value As Integer) items.Add(value) End Sub Public Function GetEnumerator() As IEnumerator(Of Integer) _ Implements IEnumerable(Of Integer).GetEnumerator Return items.GetEnumerator() End Function Private Function IEnumerable_GetEnumerator() As IEnumerator _ Implements IEnumerable.GetEnumerator Return GetEnumerator() End Function End Class ' Kullanım: Dim col As New IntCollection() col.Add(10) col.Add(20) col.Add(30) For Each n As Integer In col Console.WriteLine(n) Next
Temel Özellikler:
Arayüzü IEnumerable olmadan, sadece GetEnumerator yöntemi yazarak For Each'i uygulamak mümkün müdür?
Hayır, Visual Basic, koleksiyonu For Each ile uyumlu hale getirmek için resmi olarak IEnumerable/IEnumerable(Of T) arabirimi desteği gerektirir.
Enumeratör ayrı bir sınıf olmalı mıdır?
Hayır, eğer elemanların veri tabanı standart bir enumeratörü destekliyorsa (örneğin, List(Of T) agregasyonu yapıyorsanız), onun GetEnumerator'ını döndürebilirsiniz. Sadece karmaşık senaryolar için kendi IEnumerator sınıfınız gerekebilir.
For Each döngüsü içinde koleksiyonu değiştirmek mümkün mü?
Hayır, döngü sırasında koleksiyonu değiştirmek InvalidOperationException hatasına yol açar. Doğru şekilde işlemek için özel stratejilere ihtiyaç vardır (örneğin, döngüden önce listeyi kopyalamak veya indeksleme kullanmak gibi).
Şirket, MyCollection adında kendi sınıfını bir dizi aracılığıyla ekleme ve silme ile geliştirmiş ancak IEnumerable arayüzünü uygulamamıştır. For Each çalışmıyordu, normal döngüler ve elemanlarla bir genel alan kullanmak zorunda kalıyordu.
Artılar:
Eksiler:
Sınıf, IEnumerable(Of T) uygulayacak şekilde yeniden yapılandırıldı. Sonrasında koleksiyon kolaylıkla ve standart bir şekilde For Each içinde kullanıldı ve LINQ ile uyumlu hale geldi.
Artılar:
Eksiler: