24 Mart 2011 Perşembe

C# Delegate Nedir?

5 temel tipten biri olan delegelerin kullanım amaçları, metot adresi saklamaktır. Bazen metotlarımızı, ihtiyacımız olduğu anda çalıştırmak isteyebiliriz. Olay(event) tabanlı programlama ve asenkron programlama yaparken, anonim metot yazarken delegelerden faydalanırız. Bir diğer kullanım amacı da, bir metoda parametre olarak başka bir metot verebilmektir. Bu yazımızda temel olarak delegenin ne olduğununu, nasıl tanımlandığını, nasıl kullanıldığını ve nasıl bir mantıkla çalıştığını inceleyeceğiz.

Delegeler referans türlü bir tiptir. Dolayısı ile nesneleri heap’de durur. Girişte bahsettiğimiz gibi, görevleri metot adresi tutmaktır. Burada dikkat edilmesi gereken nokta; delegenin imzası, tuttuğu metodun imzası ile aynı olmalıdır. İmzadan kastımız, geriye dönüş tipi ve aldığı parametrelerdir. Bir delege, birden fazla metot adresi tutabilir. Bu durumda FIFO (ilk giren ilk çıkar) prensibi geçerlidir. Yani metotlar, delegeye bağlanma sırasına göre çalışırlar. Sonuç almak istediğimiz zaman, en son eklenen metodun yaptığı işi görürüz.

Şimdi basit bir örnek ile anlatmak istediklerimizi incelemeye çalışalım.

namespace DelegeKavrami

{

    delegate void Temsilci(); //Tanımladığımız bu delege, geriye dönüş tipi void olan ve parametre almayan metotların adreslerini saklayabilir.

   

    class Program

    {

        static void Main(string[] args)

        {

            Temsilci t = new Temsilci(Test);

            t.Invoke();

        }

 

        static void Test()

        {

            Console.WriteLine("Metot çalıştı");

        }

    }

}

İlk olarak, adresini tutacağımız metodun imzasına uygun bir delege tanımladık. Daha sonra Main metodu içerisinde, delege nesnemizi oluşturduk ve constructor metoduna parametre olarak metodumuzun adını verdik. t değişkeni üzerinden invoke metodunu çağırdımızıda da metodumuzu çalıştırmış olduk. (metodumuz parametre alsaydı, invoke metoduna parametre değerlerini vermemiz gerekecekti.)

Untitled

 

Şimdi de bir delegeye birden fazla metot bağladığımızda nasıl bir sonuç alacağımızı incelemeye çalışalım.

namespace DelegeKavrami

{

    delegate int Matematik(int x);

   

    class Program

    {

        static void Main(string[] args)

        {

            Matematik canta = new Matematik(KareAl);

            canta += new Matematik(KupAl);

            Console.WriteLine(canta.Invoke(5));

        }

 

        static int KareAl(int sayi)

        {

            return sayi * sayi;

        }

 

        static int KupAl(int sayi)

        {

            return sayi * sayi * sayi;

        }

    }

}

Yukarıdaki kod parçasını çalıştırdığımızda alacağımız sonuç aşağıdaki gibidir.

Untitled2

Delegemize iki metot bağlamamıza rağmen, invoke metodunu çağırdığımızda en son eklenen metodun çalıştığını gördük.

Son olarak yazım kolaylıklarından bahsedelim.

1) Bir delegeye += ile metot ekleyebildiğimiz gibi, –= ile de metot çıkartabilmemiz mümkündür.

Matematik canta = new Matematik(KareAl);

canta += new Matematik(KupAl);

canta -= new Matematik(KupAl);

Bu aşamada delegemizi invoke ettiğimizde KareAl metodu çalışacaktır.

2) Delege nesnesi oluştururken, new …(..) yazmayabiliriz.

Matematik canta = KareAl;

canta += KupAl;

Console.WriteLine(canta.Invoke(5));

3) canta değişkeni üzerinden invoke etmek yerine, bu değişkene direkt olarak parametreleri verebiliriz.

Matematik canta = new Matematik(KareAl);

int sonuc = canta(5);

 



11 yorum:

Adsız dedi ki...

10 numara anlatım , eline saglık kardeşim....

Musti dedi ki...

Duzeltme :

Burda bir yanlislik var "Delegemize iki metot bağlamamıza rağmen, invoke metodunu çağırdığımızda en son eklenen metodun çalıştığını gördük"

FIFO yani first in first out olmasi gerekir. En son eklenen calisir olmamasi gerekiyor

Onur Salkaya dedi ki...

Merhaba,

Delegeler üzerine birden fazla metot bağlanabilir ve bu delege üzerinden Invoke metodu çalıştığında tüm metotlar arka planda çalışır. Yani söylediğiniz gibi ilk giren metot çalışmaya başlar ve eklenme sırası ile bu işlem devam eder. Ancak sonuç elde etme kısmında durum farklıdır, Invoke metodunun geriye döndüğü bir değer varsa, bu değer en son çalışan metot sonucu elde edilen değerdir.

Adsız dedi ki...

Güzel bir blog, bilgiler için teşekkürler. Bir soru sormak istiyorum, Delegate 1'den fazla method'u tutabiliyor ama sonuncu girilen parametreyi (yani methodu) baz alarak sonuc gösteriyor, peki ben ilk girilen ya da sondan bir önceki methodun değerini almak istediğimde index değeri gibi bir yöntemle erişebiliyor muyum method'a? Şimdiden teşekkürler.

C.a dedi ki...

Güzel anlatım teşekkürler

Adsız dedi ki...

static void Main(string[] args)

{

Matematik canta = new Matematik(KareAl);

çanta += new Matematik(KupAl);

Console.WriteLine(canta.Invoke(5));

}

Bu kod parcasinda once çanta delegate nesnesine bagli ne kadar metod varsa(100 tane bile olsa), hepsi calisiyor, ondan sonra diger satira geciliyor (Console.WriteLine(...)) , dogru mu ?
Bi de

Adsız dedi ki...

Matematik canta = new Matematik(KareAl);

canta += new Matematik(KupAl);

Console.WriteLine(canta.Invoke(5));
BU KISIMDA KAREAL METODUNUN ÇALIŞMASI GEREKMEZ Mİ FİFO MANTIĞINA GÖRE.Yardımcı olabilirseniz seviniirm

Onur Salkaya dedi ki...

Merhaba,

Aslında delegeye bağladığınız tüm metotlar arka planda çalışıyor. Sizin de söylediğiniz gibi FİFO prensibi ile çalışıyor. Ancak delege üzerinden ilgili metodun dönüş değerini aldığınızda en son çalışan metodun sonucunu elde edersiniz. Yukarıdaki örnekte Önce KupAl metodu çalışır, ardından da KareAl metodu çalışır, ancak Invoke metodu geriye tek bir int döner, bu da en son çalışan metodun sonucudur.

Adsız dedi ki...

Hocam merhaba,
static int KareAl(int sayi)
{
int sonuc = sayi * sayi;
Console.WriteLine("KareAl Metodu Sonucu = " + sonuc);
}

static int KupAl(int sayi)
{
int sonuc = sayi * sayi;
Console.WriteLine("KupAl Metodu Sonucu = " + sonuc);
}

şeklinde çalıştırırsanız FIFO şeklinde çalıştığını görebilirsiniz.

Onur Salkaya dedi ki...

Merhaba, öncelikle yorum için teşekkür ederim. zaten çalışma şeklinin FİFO olduğunu belirtmiştim. Ama metotlar geriye "int" dönüyor. Delege de en nihayetinde tek bir integer dönecek. Bu değer her zaman son çalışan metodun sonucu olur. Ekrana Console.WriteLine ile sonucu yazdırmak metottan geriye değer dönmek değildir. Ayeıca yazdığınız kod bloğu doğru değil. Geriye int dönen bir metot var herhangi bir return ifadesi kullanmışsınız.

Adsız dedi ki...

Guzel anlatmissin sağol

Yorum Gönder