C# Döngülerini Anlamak: foreach
Döngülerinde IEnumerator<T>
Kullanımı
C#’ta koleksiyonlarla çalışmak ve verileri döngüye almak, geliştiriciler için temel bir uygulamadır. Bir metodun IEnumerator<T>
döndürmeye çalışırken ve bunu foreach
döngüsünde kullanırken sıkça karşılaşılan bir soru vardır. Bu soru, kullanıcı arayüzündeki iç içe geçmiş kontrolleri geçmeniz gerektiğinde daha da ilginç hale gelir.
Bu durumu daha derinlemesine inceleyerek sorunun özünü keşfedelim ve pratik bir çözüm sunalım.
Sorun
Diyelim ki, yüksekliklerini dinamik olarak ayarlamak istediğiniz bir Windows Form’u var. Bu TextBox
kontrolleri formun kök seviyesinde yer almayabilir; bazıları diğer kontrollerin içinde yer alabilir ve karmaşık bir yapı oluşturabilir. Bulunan TextBox
‘ları birer birer döndürmek için yield
kullanan bir metot kullanmak istiyorsunuz.
Başlangıçtaki yaklaşımınız muhtemelen şöyle görünecektir:
private static IEnumerator<TextBox> FindTextBoxes(Control rootControl)
{
foreach (Control control in rootControl.Controls)
{
if (control.Controls.Count > 0)
{
// Her bir alt kontrol içinde TextBox'ları özyinelemeli olarak ara
foreach (TextBox textBox in FindTextBoxes(control))
{
yield return textBox;
}
}
TextBox textBox2 = control as TextBox;
if (textBox2 != null)
{
yield return textBox2;
}
}
}
Ancak, bu metodu şu şekilde bir foreach
döngüsünde kullandığınızda:
foreach(TextBox textBox in FindTextBoxes(this))
{
textBox.Height = height;
}
Bir derleyici hatası ile karşılaşırsınız. Hata, foreach
döngüsünün bir IEnumerable
beklemesinden kaynaklanır, fakat metodunuz IEnumerator
döndürmektedir.
Çözüm
Bu sorunun çözüm anahtarı, metodunuzun dönüş türünü IEnumerator<T>
‘den IEnumerable<T>
‘ye değiştirmektedir. C#’ta yield return
sözdizimi, metodun ayrı bir enumeratör sınıfı ihtiyaç duymadan etkili bir şekilde bir iteratör üretmesini sağlar.
Metodunuzu şu şekilde güncelleyebilirsiniz:
Güncellenmiş Metod
private static IEnumerable<TextBox> FindTextBoxes(Control rootControl)
{
foreach (Control control in rootControl.Controls)
{
// Alt kontrollerin olup olmadığını kontrol et
if (control.Controls.Count > 0)
{
// Alt kontrollerdeki TextBox'ları özyinelemeli olarak ara
foreach (TextBox textBox in FindTextBoxes(control))
{
yield return textBox;
}
}
// Mevcut kontrol bir TextBox ise, döndür
if (control is TextBox textBox2)
{
yield return textBox2;
}
}
}
Açıklama
-
Dönüş Türünü Değiştirin: Metod artık
IEnumerator<TextBox>
yerineIEnumerable<TextBox>
döndürmektedir. Bu, onun doğrudan birforeach
döngüsünde kullanılmasını sağlar. -
yield return
Kullanımı:yield return
kullanımının temiz ve etkili bir yolu, döngü ilerledikçeTextBox
kontrollerini elde etmeyi sağlar.
Bu değişiklikle, metodunuzu foreach
döngüsünde kullandığınızda artık sorunsuz çalışacaktır ve her bir TextBox
ayrı ayrı işlenecektir.
Sonuç
C# koleksiyonları ve foreach
döngüleriyle çalışmak, özellikle de özyinelemeli metotlar ve kontrol yapılarını yönetirken beklenmedik engellerle karşılaşmanıza neden olabilir. Dönüş türünü IEnumerator<T>
‘den IEnumerable<T>
‘ye değiştirerek, döngü yapılarında ek karmaşıklıklara yol açmadan numaralandırmayı kolayca kullanabilirsiniz.
Bu yaklaşımı takip ederek, yalnızca derleyici hatalarından kaçınmakla kalmaz, aynı zamanda formunuzdaki iç içe geçmiş kontrollerle çalıştığınızda kodunuzun bakımını ve okunabilirliğini artırırsınız.
Daha fazla bilgi için, IEnumerable, IEnumerator ve yield
anahtar kelimesi gibi kavramlarla ilgili bilgi edinin ve C#‘ın iterasyon yeteneklerinden tam anlamıyla yararlanın.