12 Şubat 2011 Cumartesi

C#'da yield Kavrami

Daha onceki makalelerde Foreach iterasyonu hakkinda bilgi vermistim. Kisaca hatirlatacak olursak, IEnumerable interfacesini implement etmeyen bir class foreach iterasyonuna sahip olamiyordu. Bunun icin, o class'i IEnumerable interfacesinden implement edip, bu implementle birlikte override edilmesi gereken GetEnumerator metodunun icini doldurdugumuz zaman, artik bizim yazdigimiz sinifta da foreach ile gezebilecek duruma geliyorduk. Sunu da unutmayalim ki, GetEnumerator metodunu override ederken, MoveNext(), Reset() metotlarini ve Current isimli uyesinin iclerini doldurmamiz gerekiyordu.

Mantigi oldukca basit ama bazi projelerde, uygulamaya entegrasyonu sıkıntı çıkarabiliyor. Iste bu  sıkıntıları gidermek için C# 2.0 ile birlikte gelen yield keywordu sayesinde bu islemlerin tumu bizim icin arka planda yapilmis olacak.

Kullanimi oldukca basit;

Yine ayni sekilde, UrunYonetim sinifini olusturup, IEnumerable sinifindan kalitalim ve GetEnumerator sinifini override edelim.


namespace yieldKullanimi
{
    class UrunYonetim : IEnumerable
    {
        Urun[] _urunler;

        public UrunYonetim()
        {
            _urunler = VeriTabanindanOku();
        }

        private Urun[] VeriTabanindanOku()
        {
            Urun[] urunler = { new Urun(1, "Monitor", 200), new Urun(2, "Klavye", 80), new Urun(3, "Mouse", 40) };

            return urunler;
        }

        public IEnumerator GetEnumerator()
        {
            for (int i = 0; i < _urunler.Length; i++)
            {
                yield return _urunler[i].Ad;  
            }
        }
    }
}

Gordugunuz uzere, GetEnumerator sinifinda, onceden bir numarator sinifi olusturup(IEnumerator interfacesini implement eden sinif) nesnesini burada olusturup return ediyorduk. Daha sonra da MoveNext,Reset ve Current gibi uyelerin icini dolduruyorduk. Tum bunlari, GetEnumeratorun icine yazdigimiz kodlar yapiyor iste. for dongusuyle sayesinde, MoveNext metodunun ici yaziliyor. int i=0 diyerek Reset() metodunu cagiriyoruz, yield return_urunler[i].Ad diyerek de aslinda Current field'ini okuyoruz. Bunun sonucunda da, biz Urun sinifinin icinden string tipinden dolasip, urun isimlerini elde edebilecegiz.

Simdi de IL Disassambler(ILDASM) acarak, fiziksel olarak yazmadigimiz halde hangi metotlarin(uyelerin) olusturulduguna bakalim.


Gordugunuz uzere, biz MoveNext,Reset ve Current gibi uyeler yazmamamiza ragmen, yield keywordu sayesinde, arka planda bunlarin yazildigini goruyoruz. Programimiza buyuk olcude rahatlik getiren, is yukunu azaltan ayni zamanda da kod okulurlugu acisindan profesyonel yapisini koruyan yield'lar sayesinde hayat artik daha da guzel. :)

* Resme tıklarsanız, yeni ekranda, orjinal boyutunda erişebilirsiniz.

1 yorum:

Şafak dedi ki...

teşekkürler hocam