Action, Func ve Predicate Delegeleri

Delegeler metodları işaret eden ve işaret ettikleri metodlarla aynı imzaya sahip olan yani aynı tipte parametrelere ve dönüş değerlerine sahip olan yapılardır.  Delegeleri event tabanlı programlamada, asenkron programlamada, thread programlamada vb bir çok yerde kullanırız. Makalenin asıl amacı genel olarak delege yapısı olmadığı için detaylarına girmeyeceğim.

Pekala yazımızın konusu olan Action, Func ve Predicate neyi temsil eder? Başlıktan da anlaşılacağı üzere bunlar da .Net framework içerisinde bulunan, bizler için önceden hazırlanmış olan delegelerdir. Çok fazla kelimelerle uğraşmadan kod üzerinde görelim.

Action delegesinin imzasına baktığınızda aşağıdaki gibi bir kod göreceksiniz.

public delegate void Action<in T>(T obj);

Burada Action delegemizin T tipinde yani herhangi bir tipte parametre alan sonrasında da void dönüş yapan metodları işaret edebildiğini görüyoruz.

Örneğin normal delegeler ile aşağıdaki şekilde yazdığımız bir kodu

        delegate void NormalDelege(long sayi);

        private void button1_Click(object sender, EventArgs e)
        {
            NormalDelege karesiniAlDelegem;
            karesiniAlDelegem = karesiniAl;
            karesiniAlDelegem(3);
        }

        private void karesiniAl(long sayi)
        {
            MessageBox.Show(Math.Pow(sayi,2).ToString());
        }

Action delegesi ile aşağıdaki gibi yazabiliriz.

        private void button1_Click(object sender, EventArgs e)
        {
            Action<long> actionIleKaresiniAl;
            actionIleKaresiniAl = karesiniAl;
            actionIleKaresiniAl(3);
        }

        private void karesiniAl(long sayi)
        {
            MessageBox.Show(Math.Pow(sayi,2).ToString());
        }

Action delegesi olduğunun farkına varmasak da kodlarımız içinde lambda ile birlikte bu delegeyi oldukça fazla kullanmaktayız. Örneğin aşağıdaki kodda (kodun anlamsız olduğunun farkındayım amaç net şekilde gösterebilmek 🙂 )

sayilar.ForEach(x => MessageBox.Show(Math.Pow(x, 2).ToString()));

ForEach methodunun tanımına gittiğimizde Action tipinde bir parametre aldığını görebiliriz.

public void ForEach(Action<T> action);

Yani aslında biz ForEach içerisine long tipinde bir değer alan ve içerisinde bu değerin karesini alıp MessageBox ile gösteren bir fonksyion yazdık.

Func delegesi Action’a benzer bir yapıdadır ama Actiondan farklı olarak bir dönüş değeri vardır. Func delegesinin tanımlarına baktığımızda iki farklı kullanım görebiliriz. Hiç parametre almadan bir değer dönebilir.

public delegate TResult Func<out TResult>()

Ya da bir parametre alıp bir değer dönebilir.

public delegate TResult Func<in T, out TResult>(
	T arg
)

Aşağıdaki kod örneğinde butonun click eventinde öncelikle Func delegesi parametre almayıp string dönen bir metodu işaret ederken, sonrasında delegemiz string bir değişken alıp, string bir değişken dönen bir metodu işaret etmektedir.

        private void button1_Click(object sender, EventArgs e)
        {
            Func<string> stringDonenFunc;
            stringDonenFunc = merhabaDe;
            MessageBox.Show(stringDonenFunc());

            Func<long, string> longAlipStringDonenFunc;
            longAlipStringDonenFunc = karesiniAl;
            MessageBox.Show(longAlipStringDonenFunc(3));
        }

        private string merhabaDe()
        {
            return "Merhaba";
        }

        private string karesiniAl(long sayi)
        {
            return Math.Pow(sayi, 2).ToString();
        }

Func delegesini de farkında olmasak da linq sorgularımızda kullanmaktayız.  Listeler üzerinde çalıştırdığımız Select , Where vb komutlarında tanımlarına baktığımızda Func tipinde parametre aldıklarını görürüz.

Predicate delegesi ise tam olarak Func<T, bool> parametresinin yaptığı işi yapar. Yani herhangi bir tipteki değişkeni alır ve geriye boolean bir değer döner.  Kullanımı da benzer şekildedir.

        private void button1_Click(object sender, EventArgs e)
        {
            Predicate<long> predicateDelegesi;
            predicateDelegesi = ikiHaneliMi;
            if(predicateDelegesi(55))
                MessageBox.Show("Evet");
            else
                MessageBox.Show("Hayır");
        }
        private bool ikiHaneliMi(long sayi)
        {
            return sayi < 100 && sayi > 9;
        }

Kısa bir şekilde Action, Func ve Predicate delegelerini ve kullanımlarını anlatmaya çalıştım. Eğer herhangi bir sorunuz, eleştiriniz, öneriniz varsa yorum yazarsanız sevinirim.

Çevik Kalın 🙂