Showing posts with label ienumerator. Show all posts
Showing posts with label ienumerator. Show all posts

Friday, December 14, 2012

Arayüzlerin (Interface) Kullanılması (c#)


 .NET sınıfı kütüphanesinde de birçok arayüz bulunmaktadır. Her arayüz çeşitli amaçlar için yazılmıştır. Örneğin System isim alanında bulunan IDisposable arayüzü gereksiz nesne toplayıcısı (garbage collector) için gerekli olabilecek Dispose() metodunun uygulanmasını zorlar. Aynı şekilde System.Collections isim alanında bulunan IEnumarable arayüzü tanımladığımız sınıfların foreach döngü yapısı ile kullanabilmesini sağlar. IEnumarable arayüzü içindeki metotlar ilgili sınıf tarafından uygulanırsa tanımlanan bu sınıf foreach döngüsü ile kullanılabilir. Çünkü foreach döngüsü çalıştırılmaya başlanınca foreach bloğunda kullanılan sınıfn IEnurable arayüzünü uygulayıp uygulamadığını kontol edilir. Eğer bu arayüz uygulanmış ise IEnumarable arayüzündeki metotlar kullanılarak foreach döngüsü işletilir.Bu konumuzda IEnumarable arayüzünün kullanımına bir örnek vereceğiz.

IEnumarable arayüzünü uygulayan bir sınıf foreach döngü yapısı ile kullanılabildiğini söylemiştik. Tabi foreach döngü yapısı ile kullanabileceğimiz bir sınıfın yapısında dizi ya da daha sonra göreceğimiz koleksiyon tabanlı bir yapının bulunması mantıklı olur.


using System;
using System.Collections;

class Koleksiyon : IEnumerable
{
    int[] Dizi;
    public Koleksiyon(int[] dizi)
    {
        this.Dizi = dizi;
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return new ENumaralandirma(this);
    }

    class ENumaralandirma : IEnumerator
    {
        int indeks;
        Koleksiyon koleksiyon;

        public ENumaralandirma(Koleksiyon koleksiyon)
        {
            this.koleksiyon = koleksiyon;
            indeks = -1;
        }

        public void Reset()
        {
            indeks = -1;
        }
        public bool MoveNext()
        {
            indeks++;

            if (indeks < koleksiyon.Dizi.Length)
                return true;
            else
                return false;
        }

        object IEnumerator.Current
        {
            get
            {
                return (koleksiyon.Dizi[indeks]);
            }
        }
    }
}

public class MainMetodu
{
    public static void Main()
    {
        int[] dizi = {1,2,3,8,6,9,7};

        Koleksiyon k= new Koleksiyon(dizi);

        foreach(int i in k)
            Console.Write(i + " ");

        Console.ReadLine();
    }
}





Bu programı derlediğimizde ekrana

1 2 3 8 6 9 7

yazıldığını göreceğiz.

Programda neler olup bittiğine göz atmak gerekirse, Koleksiyon isimli bir sınıfın yapısındaki Dizinin eleman değerlerini foreach döngüsü ile elde etmek için Koleksiyon sınıfı System.Collections isim alanında bulunan IEnumarable arayüzünü uyguluyor. Dolayısıyla IEnumarable arayüzündeki bütün metotları uygulamalıdır. IEnumerable arayüzünde sadece

IEnumerator GetEnumerator();

metodu ile bildirilmiştir. Bu metot dizinin içerisinde dolaşmak için gerekli olan IEnumerator referansına geri dönmektedir. Bu yüzden bu metot aşağıdaki gibi yazılmıştır.

IEnumerator IEnumerable.GetEnumerator()
{
  return new Enumaralandırma(this);
}

GetEnumerator() metodunun geri dönüş değeri için IEnumerator arayüzünden türetilmiş IEnumaralandırma sınıfı bildirilmiştir. IEnumerator arayüzündeki metot ve özellikler Koleksiyon nesnesi içindeki dizinin elemanlarına erişmek için kullanılacaktır. IEnumerator arayüzünde bulunan üye elemanlar aşağıdaki gibidir.

object Current{
get;
}

bool MoveNext();

Void Reset();

Bu iç elemanında IENumaralandırma sınıfında bildirilmesi gerekir. Current özelliği koleksiyon nesnesinin herhangi bir andaki değerini gösterir. Sade get bloğunu bildirmek yeterlidir. MoveNext() metodu dizi koleksiyon dizisi içinde bir sonraki elemana geçmek için kullanılır. Eğer bir sonraki elemana geçilemiyorsa false deperini geri döner. Reset() metodu ise koleksiyon dizisini herhangi bir andaki değerini ilk elemandan önceki elemana çeker. Yani dizinin indeksi -1 olur.

IEnumaralandırma sınıfının bir tane yapıcı metodu vardır. Bu yapıcı metot ile üzerinde işlem yapılacak Koleksiyon nesnesi alınmaktadır. Yapıcı metot ile aynı zamanda ENumarandırma sınıfındaki indeks değişkenide -1 değerine çekiliyor. Reset() metodunda ise indeks değişkeni bir artırılıyor. Eğer indeks değişkeninin  yeni değeri dizinin boyutundan büyükse false değerini geri dönmektedir. Current özelliğinin object olduğuna dikkat edin. Eper bu özellik object türünden olmasaydı mğmkğn olabilecek tür dönüşümlerini hesaba katmazsak bütün işlemleri sadece Current özelliği ile aynı türden olan diziler üzerinde yapabilirdik.