İlk blog gönderisi olma özelliği taşıyan bu yazıda delegate kavramına, türlerine ve kullanımına değineceğim. Bazı konuları bildiğinizi varsayıp anlatacağım. Öncelikle delegate, aynı geri dönüş değeri ve aynı parametrelere sahip metotları tutarak çalıştıran bir türdür. Bu özelliğini generic listelere benzetebiliriz. Birden çok metodu referans edebilir. Sadece bir metodu da barındırabilir. Birden çok metot vermek zorunda değiliz ama en az 1 metodu referans etmesi gerekiyor. Delegate türümüze bir imza geçiyoruz ve kullandığımız yerlerde sadece o türden metotları kabul ediyor. Peki, bu delagate nasıl tanımlanır?
public void PrintConsole(string name, string surname){
}
Yukarıda bir fonsiyon tanımlamasını görüyoruz. Bu fonksiyonu bir delegate türüne çevirmek için delegate keywordünü kullanıp süslü parantezleri kaldırmamız gerekiyor.
public delegate void PrintConsole(string name, string surname);
Artık bir delegate türüne sahibiz. Elimizde bir imza mevcut. 2 adet string parametre alan ve geri dönüş değeri olmayan bir metodu işaret ediyor. PrintConsole bizim için bir tür oluyor. Direk kullanamıyoruz. Konsol projesi üzerinde kullanabileceğimiz yapıyı oluşturup basit bir şekilde görelim.
public class DelegateReview
{
public void FullName(string Name,string Surname)
{
Console.WriteLine(Name + " "+ Surname);
}
public void FullNameFormat(string Name, string Surname)
{
Console.WriteLine(Name + " - " + Surname);
}
public void FullNameFormat2(string Name, string Surname)
{
Console.WriteLine(Name + " | " + Surname);
}
public string FullNameFormat3(string Name, string Surname)
{
return Name + " | " + Surname;
}
public bool IsNameValid(string Name)
{
if (string.IsNullOrWhiteSpace(Name))
{
return false;
}
return true;
}
public void PrintName(string Name)
{
Console.WriteLine(Name);
}
public delegate void PrintConsole(string name, string surname);
public PrintConsole printConsole;
}
Tanımladığımız delegate yapısını printConsole değişkeni üzerinden kullanacağız. Değişken tipi olarak oluşturduğumuz delegate yapısını belirttik. Örnek bir metodu da sınıfımız içerisine tanımladık. Şimdi de main metoduna geçip kullanımını görelim.
DelegateReview example= new DelegateReview();
//example.printConsole = example.FullName("nameValue","surnameValue");
//example.printConsole = new PrintConsole();
example.printConsole = new PrintConsole(example.FullName);
example.printConsole.Invoke("nameValue", "surnameValue");
Console.ReadKey();
Öncelikle sınıfımızdan nesne örneği aldık. İlk yorum satırındaki kod hata verecektir. Ya metot adını vereceğiz ya PrintConsole türünden nesne örneği alacağız. Parantez açtığımız zaman fonksiyonu vermiyoruz, fonksiyonu çağırmış oluyoruz. İkinci yorum satırındaki kod da bize hata verecektir. Yukarıda belirttiğim gibi en az 1 metodu referans olarak göstermeli. DelegateReview içerisinde uygun bir metodumuz vardı. Bu metodun adını parametre olarak veriyoruz. Invoke ile oluşturduğumuz delegate içerisinde yer alan metotların çalışmasını sağlıyoruz. 1 veya n adet referanslı metodu çalıştırıyor. FullName ismindeki metot yerine başka sınıfların içerisindeki metotlar da verilebilir. Şimdiye kadar basit bir şekilde delegate tanımlamasını ve kullanımını gördük.
example.printConsole += example.FullNameFormat;
//example.printConsole = example.printConsole + example.FullNameFormat
example.printConsole += example.FullNameFormat2;
example.printConsole.Invoke("nameValue", "surnameValue");
Console.WriteLine("-----");
example.printConsole -= example.FullName;
example.printConsole += example.FullNameFormat2;
example.printConsole.Invoke("nameValue", "surnameValue");
Console.ReadKey();
+= operatörü ile mevcut delegate nesnemize yeni değerler ekleyebiliyoruz. = operatörünü kullanırsak referans edilen diğer metotlar kaybedilir. += ile üzerine ekliyoruz. -= ile metotları çıkarıyoruz. FullNameFormat2 ismindeki metot yukarıdaki örneğimizde 2 kez eklendi. Tanımladığımız delage 2 kez FullNameFormat2 ismindeki metodu referans ediyor ve 2 kez çalışacak.
Genel olarak delegate yapısı ve işleyişi bu şekilde. Şimdi delegate türlerine geçelim.
Delegate Türleri
Framework içerisinde önceden tanımlanmış func, predicate ve action olmak üzere 3 adet delegate sınıfımız vardır. Birçok ihtiyacımızı karşılamaktadırlar.
Func Delegate
Diğer delegateler içinde en kapsamlısıdır. Generic bir yapısı vardır. 16'ya kadar parametre alabilir. Geri dönüş değeriyle 17 adet tip tanımlanabilir. En sondaki tip geri dönüş tipi olarak kabul edilir. Geri dönüş tipi void olamaz. Bunun için action delegate var. Void dışında bir geri dönüş tipi belirtmemiz gerekecek. Predicate delegate yapısını birazdan inceleyeceğiz. Geriye sadece bool tipinde değer dönüyor. Func delegate bool tipini geriye dönebilir. O konuda sıkıntı yok.
Func<int, string, string> func = new Func<int, string, string>(functionName);
Bu örnekte func delegate yapımızın referans edeceği metotların 2 parametresi olacağını görüyoruz. İlk parametre int olacak. İkinci parametre string olacak. Son tip geri dönüş değerine karşılık geliyordu. Geriye string döndürecek. Bu imzaya uygun metotları ekleyebiliriz.
Predicate Delegate
Func delegate ile aynı şekilde kullanılıyor. Aralarındaki fark geri dönüş tipi belirtmiyoruz. Geriye sadece bool tipini dönüyor ve sadece 1 tane parametre alabiliyor. Tip olarak sadece parametreyi belirtiyoruz.
Action Delegate
Predicate delegate ile benzer diyebiliriz. Tek fark geri dönüş tipinin void olmasıdır. Aşağıda bazı örnek kullanımları görebilirsiniz.
Func<string, string, string> func = example.FullNameFormat3;
string funcValue= func.Invoke("FuncName","FuncSurname");
Predicate<string> predicate = example.IsNameValid;
bool predicateValue = predicate.Invoke("s");
Action<string> action = example.PrintName;
action.Invoke("action");
Console.ReadKey();
Kullanım Yerleri
✷ Linq sorguları
✷ Event ile kullanılarak bazı kodların çalıştırılması
✷ Birden fazla metodun çağırıldığı durumlar
Belli başlı kullanım yerleri bunlardır.
Yorumlar
0 yorum