Bu makalemiz de IEnumerable ve IEnumerator Interfacelerinden bahsediyor olacağız. Makalemize şöyle bir soru ile başlayalım. Normal şartlar altında bir dizi ile veya bir ArrayList nesnesi ile kullandığımız foreach döngüsünü kendi yazdığımız sınıf için de kullanabilir miyiz ?
Cevap : Hayır J
int[] sayilar=new int[10];
ArrayList liste = new ArrayList();
Yukarıdaki nesnelerin hepsinde foreach döngüsü ile çalışabiliriz. Fakat sorumuz şu ki :
class Ogrenci
{
}
class Sinif
{
Ogrenci[] ogrenciler = new Ogrenci[20];
}
Sinif liste = new Sinif();
foreach (Ogrenci ogr in liste)
{
//Kodlarımız...
}
şeklinde kullanamayız. Bunun sebebi foreach döngüsü üzerinde gezineceği nesnenin IEnumerable ve IEnumerator dedigimiz interfaceler den implemente etmiş olmasını ister.
Foreach döngüsü koleksiyonlar ve diziler üzerinde ilerlemek üzere hazırlanmıştır. Peki ben kendi yazdığım sınıf ile foreach döngüsünü kullanmak istiyorsam ne olacak ?
Makalenin bundan sonraki bölümüne örneğimiz üzerinden devam edelim. Örneğimizde Ogrenci adında bir class ve bir de Sinif isminde bir class olacak.
Ogrenci.cs :
public class Ogrenci
{
public string isim;
public string soyisim;
public Ogrenci(string Isim, string SoyIsim)
{
this.isim = Isim;
this.soyisim = SoyIsim;
}
}
Sinif.cs :
public class Sinif:IEnumerator,IEnumerable
{
Ogrenci[] liste = new Ogrenci[0];
public void OgrenciEkle(Ogrenci ogr)
{
Array.Resize(ref liste, liste.Length + 1);
liste[liste.Length - 1] = ogr;
}
public Sinif()
{
}
int ind = -1;
#region IEnumerator Members
public object Current
{
get { return liste[ind]; }
}
public bool MoveNext()
{
if (++ind < liste.Length)
return true;
else
return false;
}
public void Reset()
{
ind = -1;
}
#endregion
#region IEnumerable Members
public IEnumerator GetEnumerator()
{
return (IEnumerator)this;
}
#endregion
}
Hazırladığımız iki sınıfı açıklayalım. Birinci class yani Ogrenci ismindeki sınıf sadece öğrenci bilgilerini taşımakla görevli. Ikinci class yani Sinif ise Ogrenci türünden degerleri alıp bunları kendi içerisinde ki Ogrenci dizisinde saklamakla görevli. Fakat Sinif ismindeki sınıfımızı foreach içerisinde kullanmaya çalıştığımız da eğer IEnumerable ve IEnumerator interface lerinden implemente etmezsek derleme anında şöyle bir hata alacağız :
foreach statement cannot operate on variables of type 'IEnumeratorIEnumerable.Sinif' because 'IEnumeratorIEnumerable.Sinif' does not contain a public definition for 'GetEnumerator'
Bu hata da belirtilen Sinif class ımızın GetEnumerator isminde bir üyeye sahip olmadığıdır. Foreach döngüsü çalışabilmek için bu metotu istediginden dolayı sınıfımızı IEnumerable interface den implemente etmeliyiz. Bununda haricinde foreach döngüsü tarafından kullanılan özel bir interface daha vardır ve üzerinde döndüğü koleksiyonda IEnumerator interface inin üyelerini görmek ister bunlar ise örnekte açıkça belirtilen
· Current
· MoveNext
· Reset
üye metotları ve property leridir. Bu üyeler sayesinde foreach, sınıfımızın üzerinde gezerken dizinin elemanlarına ulaşabiliyor olacaktır.
IEnumerator Interface i hakkında detaylı bilgi için bu makaleden yararlanabilirsiniz
Örneğin Current isminde ki property okunduğu zaman kendisine Ogrenci[] dizimiz içerisinden index olarak üzerinde durulan Ogrenci sınıfını vereceğiz.
public object Current
{
get { return liste[ind]; }
}
Bu property ile ind ismindeki degiskenin degeri örnegin 5 ise Ogrenci dizimizin 5 indexli gözündeki Ogrenci sınıfını kullanıcıya object türünden geri döndürüyoruz.
MoveNext metotu :
public bool MoveNext()
{
if (++ind < liste.Length)
return true;
else
return false;
}
Foreach döngümüz sınıf içerisinde ileri yönlü hareket edebilmek için MoveNext ismindeki metotumuzu kullanacaktır. Boolean türden deger döndüren bu metot döngüye dizinin son elemanına gelinip gelinmediğini bildirir. Böylece döngü ilerleyebildim mi yoksa ilerleyemedim mi gibi bir soruyu rahatlıkla sorabilir.
Reset ismindeki metot ise foreach döngüsünü dizinin ilk gözüne konumlandıracak olan metottur.
Bu kuralları uyguladıktan sonra artık sınıfınızı aşağıdaki şekilde kullanabilirsiniz :
Sinif liste = new Sinif();
liste.OgrenciEkle(new Ogrenci("haydar", "bağrıyanık"));
liste.OgrenciEkle(new Ogrenci("muhittin", "Windows"));
foreach (Ogrenci ogr in liste)
{
MessageBox.Show("Adı : " + ogr.isim+"\nSoyadı : "+ogr.soyisim);
}
Bir sonraki makalede görüşmek üzere hepinize iyi çalışmalar
Sorularınız için mail adresim :
bora.burgucugil@bilgeadam.com
BilgeAdam BTA Beşiktaş