4 Ekim 2011 Salı

C# Lambda Operatörü

Daha önceki yazılarımda Anonim metot yapısından bahsetmiştim. Kısaca hatırlayalım; bir metot bizden parametre olarak bir delege istiyorsa, aslında bir metot göndermemizi ister. Zaten delegeler metot adresleri taşıdığından dolayı, parametre olarak bir delege göndermek, o imzaya uygun bir metot göndermek ile aynı anlamdadır. Bazı durumlarda bizden parametre olarak delege göndermemizi isteyen metotlar, sadece o iş için gerekli olabilir. Yani projede herhangi başka bir yerde kullanılmaz. Bu nokta anonim metot yapısı devreye girer. Söz konusu metot sadece tek bir işlem için kullanılacaksa, isim verip ayrıyeten tanımlamak yerine, o işlem bloğu içerisinde anonim olarak tanımlamayı tercih ederiz. Çok kısa bir örnek veremek gerekirse, parametre olarak integer alan ve geriye bir integer dönen bir metota ihtiyacımız olduğunu varsayalım. Bunun için aynı imzaya sahip bir delege tanımayalım ve tanımladığımız metot adresini bu delege üzerinde taşıyalım.

delegate int MatematikHandler(int a);

 

    class Program

    {

        static void Main(string[] args)

        {

            Test(KareAl);

        }

 

        static int KareAl(int sayi)

        {

            return sayi * sayi;

        }

 

        static void Test(MatematikHandler metot)

        {

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

        }

    }

KareAl adlı metodun sadece bu kod parçasında kullanıldığı varsayılırsa, bu isimde bir metot tanımlamak yerine anonim olarak tasarlamayı tercih edebiliriz.

delegate int MatematikHandler(int a);

 

    class Program

    {

        static void Main(string[] args)

        {

            Test(delegate(int a)

            {

                return a * a;

            });

        }

 

        static void Test(MatematikHandler metot)

        {

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

        }

    }

Test adlı metot bizden MatematikHandler tipinden bir parametre beklemektedir. Bunun anlamının, MatematikHandler ile aynı imzaya sahip bir metot göndermemiz olduğundan bahsetmiştik. Biz de bu imzaya bir metot tanımlamak yerine, metodu anonim olarak yazdık ve aynı sonucu elde ettik.

İşte bu notkada lambda operatörünün işlevinden söz edebiliriz. Yukarıda tanımladığımız anonim metot içeriğini daha da kısa yazmamızı ve okunurluğu kolaylaştırmayı sağlar. Aşağıdaki kod bloğu, yukarıdakiler ile aynı sonucu verecektir.

delegate int MatematikHandler(int a);

 

    class Program

    {

        static void Main(string[] args)

        {

            Test((sayi) => sayi * sayi);

        }

 

        static void Test(MatematikHandler metot)

        {

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

        }

    }

Operatörden önce parametreleri verdik, daha sonra da return sözcüğü kullanmadan geriye dönecek ifadeyi verdik. Yazdığımız anonim metot, 1 adet int parametre alan ve geriye aldığı bu parametrenin karesini döndüren bir metottur.

Şimdi de MatematikHandler üzerinden gidelim. Delegeye sırayla 3 metot bağlayalım ve bu metotları anonim olarak tasarlayalım.

delegate int MatematikHandler(int a);

 

    class Program

    {

        static void Main(string[] args)

        {

            MatematikHandler bizimDelege = delegate(int sayi)

            {

                return sayi * sayi;

            };

 

            bizimDelege += delegate(int sayi)

            {

                return sayi + sayi;

            };

 

            bizimDelege += delegate(int sayi)

            {

                return sayi - sayi;

            };

        }

    }

İlk metot sayının karesini, ikinci metot sayının kendisi ile toplamını, üçüncü metot ise sayının kendisi ile farkını vermektedir. Şimdi bu işlemlerin aynısnı lambda operatörü ile yapalım.

delegate int MatematikHandler(int a);

 

    class Program

    {

        static void Main(string[] args)

        {

            //MatematikHandler bizimDelege = (sayi) => sayi * sayi;

            //Alt satır ile aynıdır, tek parametre olduğu için parantez koymayabiliriz.

           

            MatematikHandler bizimDelege = sayi => sayi * sayi;

 

            bizimDelege += sayi => sayi + sayi;

 

            bizimDelege += sayi => sayi - sayi;

        }

    }

Görüldüğü gibi, lambda operatörü bizim için işleri baya kolaylaştırmaktadır. İlk görüşte bu syntax size garip gelse de, hızlı bir şekilde alışabileceğinizi düşünüyorum.

Son olarak, 3 adet integer parametre alan ve geriye bu sayıların toplamını geriye döndüren bir metot yazalım.

delegate int ToplamHandler(int a, int b, int c);

 

    class Program

    {

        static void Main(string[] args)

        {

            ToplamHandler toplam = (sayi1, sayi2, sayi3) => sayi1 + sayi2 + sayi3;

           

            Console.WriteLine(toplam.Invoke(5, 10, 15));

        }

    }

Programı çalıştırdığımızda aşağıdaki sonucu göreceğiz.

Untitled

İhtiyaç duyduğumuz iş parçası sadece o an için kullanılacaksa, isim verip sınıf içerisinde tanımlamak yerine anonim olarak tasarlanmalıdır. Bunu da lambda operatörü ile kolayca yapabiliriz. Bir metot bizden delege istiyorsa, o delegenin imzasına sahip bir metot göndermemizi beklemektedir, biz de lambda operatörü ile o imzaya sahip anonim bir metot tasarlayabiliriz. LINQ mimarisinde bu yapıyı sıkça göreceğiz, bunu da ilerleyen yazılarımda ele almaya çalışacağım. Faydalı olması dileği ile…



2 yorum:

Unknown dedi ki...

Ben bu yazidan ve ingilizce kaynaklardan okudugum kadariyla yalnis anlamadiysam , => opertatoru delegate kullanma geregini ortadan kaldiriyor, dogru mu bu ?

Onur Salkaya dedi ki...

Merhaba,

Lambda operatörü, anonim metot yazmanın en kolay yoludur. Olaya delegate kullanmak olarak bakmayın, bir metot mutlaka bir delege ile işaret edilir. Sadece bir yazım kolaylığı olarak düşünebilirsiniz.

Yorum Gönder