2.0’dan önceki C# sürümlerinde bir delegate’i tanımlamak için daha önce tanımlanmış bir metod(named method) kullanmak gerekirdi. C# 2.0 ile birlikte C++’taki inline metodlar gibi isimli metod zorunluluğu ortadan kaldırılmış olup isimsiz metod da kullanılma imkanı sunulmaktadır. Anonymous Method sayesinde bir kod bloğunu, delegate tanımlamasında parametre olarak geçebileceğiz. Delegate çalıştığı zaman kendisine parametre olarak geçilmiş kod bloğunu çalıştırır. Önceki sürümlerden bildiğimiz şekliyle bir delegate tanımlayalım;
button1.Click += new EventHandler(Metod); void Metod(object sender, System.EventArgs e) { MessageBox.Show("Button tıklandı."); }//Metod
Bu kod bloğu, anonymous method formatıyla daha sade yazılabilir. Anonymous methodlar, delegate sözcüğüyle başlamak zorundadır.
button1.Click += delegate { MessageBox.Show("Button tıklandı."); };
Click eventini temsil edecek temsilcinin parametre yapısını da delegate sözcüğünde belirtebiliriz.
button1.Click += delegate(object sender, EventArgs e) { MessageBox.Show(((Button) sender).Name +" isimli button tıklandı."); };
Eventler için delegate tanımlaması yapılırken önemli rol oynayan bu metodlar, CLR’nın “her kod bloğu mutlaka class’ın metodları içerisinde bulunmalıdır” ilkesinden dolayı CLR tarafından yürütülemezler. Bu yüzden bu kod bloğu, kodlama aşamasında isimsiz görünüyor olsa da derlenme aşamasında, tekil olarak isimlendirilmiş bir metoda dönüştürülür. Örnekteki delegate tanımlamasının MSIL kodunu inceleyelim;
Görüldüğü gibi C# derleyicisi, anonymous methodu örtmek için static bir metod oluşturmuştur.
Aşağıdaki örnekte bir delegate’in hem anonymous metod hem de named metod ile nasıl ilişkilendirildiği gösterilmiştir;
class Program { //Bir delegate tanımlayalım delegate void Islem(int X, int Y); static void Main() { //Anonymous method yapısını kullanan delegate Islem oIslem = delegate(int A,int B) { Console.WriteLine("Anonymous method sonucu : "+ (A+B)); }; oIslem(10,20); //Toplama isimli methodu kullanan delegate oIslem = new Islem(Toplama); oIslem(15,21); Console.ReadLine(); }//Main static void Toplama(int X,int Y) { Console.WriteLine("Named method(Toplama) sonucu : "+ (X+Y)); }//Toplama }//Program
Anonymous method sonucu : 30
Named method(Toplama) sonucu : 36
MSIL kodunu incelediğimizde C# compiler’ın, önceki örnekte olduğu için unique bir metod ismi kullandığını görmüş oluruz.
Bu son örnek, aynı zamanda anonymous methodların herhangi bir türde argüman da kabul ettiklerini göstermektedir. Hatta bu argümanlar, ref ve out sözcükleriyle birlikte de kullanılabilir.
class Program { //Islem isimli delegate tanımlayalım delegate int Islem(int valPrm, ref int refPrm, out int outPrm); static Islem Yazdir() { return delegate(int valPrm, ref int refPrm, out int outPrm) { Console.WriteLine("valPrm parametresinin değeri:{0}", valPrm); refPrm++; outPrm = 15; return valPrm; }; }//Yazdir static void Main() { Islem oIslem = Yazdir(); int refVar = 7; int outVar; int x = oIslem(10, ref refVar, out outVar); int y = oIslem(20, ref refVar, out outVar); Console.WriteLine("x:{0} y:{1} refVar:{2} outVar:{3}", x, y, refVar, outVar); Console.ReadLine(); }//Main }//Program
valPrm parametresinin değeri:10
valPrm parametresinin değeri:20
x:10 y:20 refVar:9 outVar:15
Metodlara dizi türünde parametre göndermek için kullanılan params sözcüğü, anonymous metodlarında kullanılamaz.
Anonymous metodlarında diğer önemli konu, lokal değişken yönetimidir. Bu metod yapısının, lokal değişkenlerin değerlerini nasıl koruduğunu bir örnek üzerinde inceleyelim;
class Program { //Sayac isimli delegate tanımlayalım delegate int DlgSayac(); static DlgSayac Sayac() { int counter = 0; DlgSayac oSayac = delegate { return ++counter; }; return oSayac; }//Sayac static void Main() { DlgSayac oSayac1 = Sayac(); DlgSayac oSayac2 = Sayac(); Console.WriteLine(oSayac1()); Console.WriteLine(oSayac1()); Console.WriteLine(oSayac2()); Console.WriteLine(oSayac2()); Console.ReadLine(); }//Main }//Program
1
2
1
2
Tanımladığımız delegate’in C# derleyicisi tarafından nasıl bir kod bloğuna çevrildiğini reflector aracılığıyla görelim.
Bu kodlar, bize şunu göstermektedir; Compiler, anonymous metodu normal metod yapısına benzetmek için yalnızca “b__0()” isimli bir metod oluşturmamış buna ek olarak “<>c__DisplayClass1″ isminde bir class oluşturmuştur. Bu class, “
Anonymous metod bloğunu, başka metodlara parametre olarak da gönderebiliriz. Önce basit bir örnek üzerinde gösterelim. Aşağıdaki tabloda rakamlardan oluşan bir dizideki çift sayıların bulunması hem named method hem de anonymous method yöntemiyle gerçekleştirilmiştir.
class Program { static void Main() { int[] Sayilar = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; int[] CiftSayilar = Array.FindAll(Sayilar, IsCift); Console.Write("Çift Sayılar : "); foreach (int Sayi in CiftSayilar) { Console.Write(Sayi +", "); } Console.ReadLine(); } //Parametre olarak gönderilmiş değerin 2'ye bölünüp bölünmediğini bildirir. static bool IsCift(int Sayi) { return (Sayi % 2 == 0); }//IsCift }//Program
class Program { static void Main() { int[] Sayilar = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; //Sayının çift olup olmadığını kontrol etmek için yeni bir metod yazılmadı. int[] CiftSayilar = Array.FindAll(Sayilar, delegate(int Sayi) { return (Sayi % 2 == 0); }); Console.Write("Çift Sayılar : "); foreach (int Sayi in CiftSayilar) { Console.Write(Sayi +", "); } Console.ReadLine(); } }//Program
Çift Sayılar : 2, 4, 6, 8, 10,
Konunun daha net anlaşılması için, daha önce generic türler konusunda gördüğümüz dizi elemanlarının sıralamasıyla ilgili bir örnek yapalım.
using System; using System.Collections.Generic; class Program { static void Main() { List <code>Yaşa göre sıralama:<br> ---------------------<br> 18 Berna Korkmaz<br> 20 Ali Korkmaz Ada göre sıralama::<br> ---------------------<br> 20 Ali Korkmaz<br> 18 Berna Korkmaz</code> Liste içerisindeki elemanları listelerken, .NET 2.0 ile birlikte gelmiş Array.ForEach() metodunu da kullanabiliriz. Bu metodun özelliği, delegate türünde parametre alabiliyor olmasıdır. [csharp]foreach (Musteri m in lstMusteri) { Console.WriteLine(m.Yas + " " + m.Adsoyad); }
satırları yerine aşağıdaki anonymous metod formatı da kullanılabilir.
lstMusteri.ForEach(delegate(Musteri m) { Console.WriteLine(m.Yas + " " + m.Adsoyad); });
Delegate konusundan hatırlanacağı gibi bir delegate’i “+=” operatörünü kullanarak birden fazla metodla ilişkilendirebiliriz. Bu metodlar aynı şekilde anonymous metod türünde de olabilir. Aşağıdaki örnekte bir delegate, iki tane anonymous metod bir tane de normal metod ile ilişkilendirilmiştir.
class Program { delegate void DelegateTip(); static void Main() { DelegateTip oDlg = delegate() { Console.WriteLine("Metod1"); }; oDlg += delegate() { Console.WriteLine("Metod2"); }; oDlg += Metod3; //Delegate'i çağıralım oDlg(); Console.ReadLine(); }//Main static void Metod3() { Console.WriteLine("Metod3"); }//Metod3 }//Program
Metod1
Metod2
Metod3
verdiğiniz örneklerden birini anlamadım.”lokal değişkenin değerini koruma” için yaptığınız örnek değeri nasıl koruyor anlayamadım. anladığım kadarı ile değer aynı kalmıyor 1-2-1-2 .burada korunan ne .ilgilenirseniz sevinirm. bloğunuz çok faydalı teşekkürler
Ahmet Bey,burada kastettiğimiz şey değişkenin en sonki değerini koruyor olmasıdır.
İlk başta değişkenin değeri “0¨ idi.
Console.WriteLine(oSayac1()); -İlk çağrımda 1 oldu
Console.WriteLine(oSayac1()); -İkinci çağrımda 2 oldu. Yani ilk çağrımdaki “1¨ değerini korumuş oldu. Yeniden “0¨ olmadı. Zaten reflector görüntüsünde görüleceği gibi değişken public olarak tanımlanıyor.
Merhabalar, sitenizi inceledim,içerik bakımından benim sitemle benzer içerikte olduğu için hoşuma gitti,Link değişimi düşünürmüsünüz?
yıllar sonra gördüm.
teşekkürler anladım.