Anonymous Methods etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
Anonymous Methods etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

C# Lambda Expressions Kullanımı

C# Anonymous Methods (İsimsiz Metodlar) Kullanımı yazımızda isimsiz metodların kullanımından bahsetmiştik. Aslında Lambda Expressions isimsiz metod yaratmanın kısa yoludur.

Lambda Expressions'ı generic List<T> sınıfının FindAll() metodu üzerinden incelemeye çalışalım.
 
     // Method of the System.Collections.Generic.List<T> class.
     public List<T> FindAll(Predicate<T> match)

Yukarıda FindAll metodunun freamwork içerisindeki tanımlamasını görüyorsunuz. Gördüğünüz gibi FindAll Predicate<T> delegelesini parametre alıyor. Predicate<T> delegesi bool döndüren ve bir parametre alan metodları saklayan generic bir parametredir. Freamwork içerisindeki tanımı şu şekildedir:

    // This delegate is used by FindAll() method
    // to extract out the subset.
    public delegate bool Predicate<T>(T obj);

FindAll metodunu çalıştırdığımızda listemizin içerisindeki elemanlar sırasıyla Predicate<T> delegesinin tuttuğu metodlara gidecek ve geriye true yada false değeri dönecektir.

Önce klasik delege tanımı ile bir liste içerisindeki çift sayıları bulan programımızı yazalım:

    class Program
    {
        static void Main(string[] args)
        {
            TraditionalDelegateSyntax();
        }

        static void TraditionalDelegateSyntax()
        {
            List<int> numbers = new List<int>();
            numbers.AddRange(new int[] { 5, 7, 9, 14, 17, 2, 6 });

            //klasik delege tanimi ile
            Predicate<int> predicate = new Predicate<int>(IsEvenNumber);
            List<int> evenNumbers = numbers.FindAll(predicate);

            foreach (int item in evenNumbers)
            {
                Console.WriteLine(item);
            }

            Console.ReadLine();
        }

        // Target for the Predicate<> delegate.
        static bool IsEvenNumber(int i)
        {
            // Is it an even number?
            return (i % 2) == 0;
        }
    }

Gördüğünüz gibi önce Predicate<int> tipinde bir delege nesnesi tanımladık. Ardından IsEvenNumber metodunu bu delegenin saklayacağı metod olarak parametre verdik. Ardından FindAll metodu ile bu delegenin taşıdığı IsEvenNumber metodunu number listemizin her adımı için çalıştırdık. Klasik yöntem ile bu şekilde FindAll metodunu çalıştırabiliriz. Şimdi birde aynı örneği Anonymous Methods ile yazalım:

        static void AnonymousMethodsDelegateSyntax()
        {
            List<int> numbers = new List<int>();
            numbers.AddRange(new int[] { 5, 7, 9, 14, 17, 2, 6 });

            //Anonymous Methods ile
            List<int> evenNumbers = numbers.FindAll(
                delegate(int i){ return (i % 2) == 0; }
                );

            foreach (int item in evenNumbers)
            {
                Console.WriteLine(item);
            }

            Console.ReadLine();
        }

Bu şekilde isimsiz metodlar ile çift sayı bulma işlemini gerçekleştirmiş olduk. İsimsiz metodlar ile ilgili detaylı bilgiye şu yazıdan ulaşabilirsiniz: C# Anonymous Methods (İsimsiz Metodlar) Kullanımı 

Son olarak Lambda Expressions ile yazımına bakalım:

        static void LambdaExpressionsSyntax()
        {
            List<int> numbers = new List<int>();
            numbers.AddRange(new int[] { 5, 7, 9, 14, 17, 2, 6 });

            //Lambda Expressions ile
            List<int> evenNumbers = numbers.FindAll(i => i % 2 == 0);

            foreach (int item in evenNumbers)
            {
                Console.WriteLine(item);
            }

            Console.ReadLine();
        }

Gördüğünüz gibi Lambda Expressions ile yazımı çok basit bir hale geldik. Compiler Lambda Expressions gördüğünde o satırı Anonymous Methods'a çevirir ve öyle yorumlar. Örneğin yukarıdaki örneği ildasm exe ile açarsanız Lambda Expressions içeren satırının Anonymous Methods'a çevrildiğini görürsünüz:

      List<int> evenNumbers = list.FindAll(delegate (int i)
      {
          return (i % 2) == 0;
      });

Lambda Expressions ile yazdığımız kod şu an sadece return işlemi yapıyor. Fakat biz birden fazla işlemi burada yaptırabiliriz:

      List<int> evenNumbers = list.FindAll((i) =>
      {
          Console.WriteLine("value of i is currently: {0}", i);
          bool isEven = ((i % 2) == 0);
          return isEven;
      });

Eğer hiç bir parametre gönderilmiyor ise metoda şu şekilde Lambda Expressions yazılır:

       VerySimpleDelegate d = new VerySimpleDelegate( 
       () => {return "Enjoy your string!";} );

Eğer birden fazla parametre gönderiliyor ise:

       VerySimpleDelegate d = new VerySimpleDelegate( 
       (msg, result) => 
         {Console.WriteLine("Message: {0}, Result: {1}", msg, result);} );

Çıktı:



Örnek Proje:

LambdaExpressionsExample.rar

C# Anonymous Methods (İsimsiz Metodlar) Kullanımı

Önceki C# Delegate Kullanımı I - Delege Nedir? ve C# Delegate Kullanımı II - Generic Delegeler yazılarımızda delege kavramından bahsetmiştik. Bu yazılarımızda delege tanımlarını daha önce tanımlanmış olduğumuz named metodlar ile yaptık. C# 2.0 ile birlikte bunu isimsiz metodlar ile yapabiliyor hale geldik.

button1.Click += delegate
{
    MessageBox.Show("isimsiz metodumuz calisti");
};

Önce daha önceki yazılarımızda named metodlar ile yazdığımız delege örneğimizi hatırlayalım:

    public class Person
    {
        public delegate void PersonChangeHandler(Person person
                    , string fieldName, string newValue);
        public event PersonChangeHandler PersonHasChanged;

        public int PersonId { get; set; }
        private string _name;
        public string Name
        {
            get { return _name; }
            set
            {
                _name = value;
                //eger method set edildi ise
                if (PersonHasChanged != null)
                    PersonHasChanged(this, "Name", value);
            }
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Person p1 = new Person() { PersonId = 1, Name = "Safak" };
            p1.PersonHasChanged += ShowChangedUser;
            p1.PersonHasChanged += SendChangedUserInformation;
            p1.Name = "Test";

            Console.ReadLine();

        }

        static void ShowChangedUser(Person p, string fieldName
            , string newValue)
        {
            Console.WriteLine(@"Person ID: {0} Field: {1} 
                    New Value: {2}", p.PersonId, fieldName, newValue);
        }

        static void SendChangedUserInformation(Person p, string fieldName
            , string newValue)
        {
            Console.WriteLine(@"Person ID: {0} Bilgilendirme maili 
                    gonderiliyor", p.PersonId, fieldName, newValue);
        }
    }

Şimdi bunu anonymous methodlar ile nasıl yaparız ona bakalım:

    public class Person
    {
        public delegate void PersonChangeHandler(Person person
                    , string fieldName, string newValue);
        public event PersonChangeHandler PersonHasChanged;

        public int PersonId { get; set; }
        private string _name;
        public string Name
        {
            get { return _name; }
            set
            {
                _name = value;
                //eger method set edildi ise
                if (PersonHasChanged != null)
                    PersonHasChanged(this, "Name", value);
            }
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Person p1 = new Person() { PersonId = 1, Name = "Safak" };

            //ÖNEMLİ!! ShowChangedUser yerine isimsiz metod kullandik
            p1.PersonHasChanged += delegate(Person p, string fieldName
            , string newValue)
            {
                Console.WriteLine(@"Person ID: {0} Field: {1}   
                    New Value: {2}", p.PersonId, fieldName, newValue);
            };

            //ÖNEMLİ!! SendChangedUserInformation yerine isimsiz metod kullandik
            p1.PersonHasChanged += delegate(Person p, string fieldName
            , string newValue)
            {
                Console.WriteLine(@"Person ID: {0} Bilgilendirme maili   
                    gonderiliyor", p.PersonId, fieldName, newValue);
            };

            //ÖNEMLİ!! parametresiz isimsiz metodda kullanabiliriz
            p1.PersonHasChanged += delegate
            {
                Console.WriteLine("Degisiklik calisti.");
            };

            p1.Name = "Test";

            Console.ReadLine();

        }
    }

Gördüğünüz gibi artık ShowChangedUser ve  SendChangedUserInformation named metodlarını kullanmadık onun yerine isimsiz metodlar ile delege tanımlarımızı gerçekleştirdik.

Burda önemli noktalardan biri en son metod atama işleminde parametresiz metod ataması yapabildik. Named metod kullansaydık buna izin verilmiyor olurdu. Çünkü named metod kullanımında metodun parametreleri ile delege tanımındaki parametrelerin uyuşması gerekmektedir.

Çıktı:




İsimsiz metodlar kod aşamasında isimsiz gözüksede derlenme aşamasında, unique olarak isimlendirilmiş bir metoda dönüştürülür. ildasm ile yazdığınız koda bakarsanız bunu açıkça görebilirsiniz.

Anonymous Methodlar:

* Anonymous methodlar, delegate sözcüğüyle başlamak zorundadır.
* Herhangi bir türde parametre kabul ettiklerini ederler. ref ve out sözcükleriyle birlikte de kullanılabilir.
* params sözcüğü, anonymous metodlarda kullanılamaz.
* Tanımlandığı sınıf içerisindeki herhangi bir değişken ile aynı isme sahip değişkeni olamaz.
* Bir metoda parametre olarak gönderilebilir. Örnek:

        int[] CiftSayilar = Array.FindAll(Sayilar, delegate(int Sayi)
        {
           return (Sayi % 2 == 0);
        });

Örnek Proje:
AnonymousMethodsExample.rar