IEnumerable ve IEnumerator’ün olayı
C#’ta iterator kavramını düşündüğümüzde tahmin ediyorum ki aklınıza gelen ilk yapı foreach yapısıdır. foreach ile bir koleksiyon ya da array üzerinde gezinerek elemanlarına ulaşabiliyoruz. Foreach arkaplanda iterator yapısını kullanır. Bugün inceliyeceğimiz konu biz yazdığımız bir sınıf içerisindeki elemanları foreach ile gezmek istesek ne yapmamız gerekiyor?
Aşağıda Main method içerisinde türetilmiş AlisverisSepeti classına ait bir nesne var ve bu nesne içerisinde bir bir dizi barındırmakta. Ancak dikkat ettiyseniz foreach döngüsünde dönmeye çalıştığımız yapı, iteratif özelliği bulunmayan normal bir class nesnesidir. İşte IEnumerable ve IEnumerator tam da burada devreye girer. İteratif özelliği olmayan nesnelere iteratif özellik kazandırarak onların foreach tarafından tanınmasını sağlar. Bu sınıfımızın iterator özelliği kazanması için IEnumerable veya IEnumerable
public class Program { static void Main(string[] args) { AlisverisSepeti sepetim = new AlisverisSepeti(); foreach (Urun urun in sepetim) Console.WriteLine("Urun: {0}, Fiyat {1}", urun.Name, urun.Price); Console.ReadLine(); } } public class Urun { public string Name { get; set; } public decimal Price { get; set; } }
Bir classın nesnesinin iteratif özellik kazanması ve foreach tarafından tanınması için IEnumerable interfacesini implemente etmesi gerekir. IEnumerable interfacesi içerisinde sadece dönüş tipi IEnumerator interafacesini implemente eden sınıf nesnesi olan GetEnumetor metodunu bulundurur. Bu metodu aşağıdaki gibi implemente ettikten sonra , metodun döneceği ve nesnenin foreachteki hareketlerini belirleyeceğimiz IEnumerator interfacesinden türeyen bir sınıf yazmamız gerekli.
public class AlisverisSepeti : IEnumerable { public Urun[] UrunListesi { get; set; } public AlisverisSepeti() { UrunListesi = new Urun[] { new Urun(){ Name="Bilgisayar", Price=1022.3m}, new Urun(){ Name="Ipad", Price=699.9m} }; } public IEnumerator GetEnumerator() { return new AlisverisSepetiEnumerator(UrunListesi); } }
Aşağıda GetEnumarator sınfının döneceği yapıyı implemente etmekteyiz. IEnumerator içerisinde 3 ana özellik bulundurur.
Current : İterasyonda kalınan yer.
MoveNext : İterasyon sırasında bir sonraki adımın var olup olmadığı yani döngünün sona ulaşıp ulaşmadığı
Reset : iterasyonu başa alan yapı.
Bu classın nesnesini GetEnumerator return’e verdiğimizde foreachte her bir iterasyon indexi artığında önce MoveNext çalışacak , yapıda sona gelip gelmediğimizi kontrol edecek eğer sona gelmediysek arkasından Current çalışıp ihtiyacımız olan elemanı bize dönecek.
public class AlisverisSepetiEnumerator : IEnumerator { private Urun[] _UrunList; int _curentIndex = -1; public AlisverisSepetiEnumerator(Urun[] urunList) { _UrunList = urunList; } //iterasyonda kalinan yer. public object Current { get { return _UrunList[_curentIndex]; } } //bir sonraki adım var mi kontrolü. public bool MoveNext() { return ++_curentIndex < _UrunList.Length; } //iterasyonu basa alir. public void Reset() { _curentIndex = -1; } }