C# Delegate Kullanım Örneği

Bu makalemde C# Delegate kavramını ve delegate’i daha etkili bir şekilde nasıl kullanacağınızı öğreneceksiniz. Ayrıca delegate konusunda detaylı bilgi almak isteyenler aşağıda ki makalemde faydalanabilirler.

C# Delegate Nedir? Kullanımı

https://alkanfatih.com/c-delegate-nedir-kullanimi/

Multicasting Delegate (Çoklu Delegate)

https://alkanfatih.com/multicasting-delegate-coklu-delegate/

C# Predicate Delegate Nedir?

https://alkanfatih.com/c-predicate-delegate-nedir/

C# Delegate Giriş

C#’ta delegateler, belirli bir parametre listesi ve dönüş türü olan metotlara yapılan başvuruları temsil eden türlerdir.

Bir delegate tanımlamak için, delegate anahtar sözcüğünü kullanır ve metot imzasını belirtirsiniz.

Örneğin:

public delegate void Greeting(string text);

Bu örnekte, bir string parametre alan ve void döndüren herhangi bir metota referans eden Greeting adında delegate türünü tanımlıyoruz.

Greeting bir delegate türü olduğundan, diğer sınıflar gibi bir sınıfın dışında ilan edebilirsiniz.

Aşağıda, Greeting delegate’iyle aynı imzaya sahip olan Program sınıfı için SayHi() metodu tanımlanır:

internal class Program
{
    private static void Main(string[] args)
    {

    }

    static void SayHi(string name)
    {
        Console.WriteLine($"Hi {name}");
    }
}

SayHi() metodunu Greeting delegate’i aracılığıyla çağırmak için, SayHi metoduyla bir Greeting delegate’i örneğini argüman olarak oluşturursunuz ve delegate örneğini Invoke() metodunu şu şekilde çağırırsınız:

Greeting greeting = new Greeting(SayHi);
greeting.Invoke("John");

Bu sözdiziminde greeting, Greeting delegate türünün bir örneğidir. Greeting delegate’i, SayHi() metodunda bir referansa sahiptir.

Greeting delegate’inin Invoke() metodunu çağırdığınızda, C# aynı bağımsız değişkenle SayHi() metodunu çağırır.

Bu nedenle, aşağıdaki ifadeler işlevsel olarak eşdeğerdir:

greeting.Invoke("Fatih");

ve

SayHi("John");

C#, SayHi metodunu bir delegate değişkenine atayarak ve başvurulan metodu delegate aracılığıyla çağırarak yeni bir Greetin delegatei örneği oluşturmanın daha kısa bir yolunu sağlar:

Greeting greeting = SayHi;
greeting("John");

Kodun Görünümü:

internal class Program
{
    private static void Main(string[] args)
    {
        Greeting greeting = new Greeting(SayHi);
        greeting.Invoke("Fatih");
    }

    static void SayHi(string name)
    {
        Console.WriteLine($"Hi {name}");
    }
}

public delegate void Greeting(string text);

Sonuç:

Hi Fatih

Delegate Niçin Kullanılır?

SayHi() metodunu doğrudan çağırabileceğimiz için, onu delege aracılığıyla çağırmanıza gerek yoktur. Peki o halde neden bir delegate kullanmaya ihtiyaç duyduk? Asıl konu bu olmalı.

Delegetler metotlara referanslar tuttuklarından, metotları delegetler aracılığıyla diğer metotlara argüman olarak iletebilirsiniz. Bu nedenle, delegateler, callback metotlar tanımlamak için idealdir.

Örneğin bir tamsayı listesini başka bir metodun sonucuna göre filtreleyen bir metot tanımlamak istediğinizi varsayalım. Bunu yapmak için bir delegate kullanabilirsiniz.

İlk olarak, bir tamsayı kabul eden ve bir boole değeri döndüren bir delegate türü tanımlayın:

public delegate bool Callback(int x);

İkinci olarak, bir tamsayı listesi ve bir Callback metodunun instance’ını kabul eden Filter() metodu tanımlayın.

    static List<int> Filter(List<int> numbers, Callback callback)
    { 
        var results = new List<int>();

        foreach (var number in numbers) 
        {
            if (callback(number))
            {
                results.Add(number);
            }
        }

        return results;
    }

Üçüncü olarak, bir sayı tek ise true döndüren isOdd() metodunu ve bir sayı çift ise true döndüren isEven() metodunu tanımlayın:

static bool IsOdd(int x) => x % 2 != 0;
static bool IsEven(int x) => x % 2 == 0;

Dördüncü olarak, Filter() metodunu çağırın ve IsEven() metoduna başvuran Callback delegate’inin bir instance’ını iletin.

var numbers = new List<int> { 1, 2, 3, 4, 5 };

var evenNumbers = Filter(numbers, IsEven);

Console.WriteLine("Çift Numaralar:");
foreach (var number in evenNumbers)
{
    Console.WriteLine($"{number}");
}

Sonuç:

Çift Numaralar:
2
4

Beşinci olarak, Filter() metodunu çağırın ve IsEven() metoduna başvuran Callback delegate’inin bir instance’ını iletin.

var oddNumbers = Filter(numbers, IsOdd);

Console.WriteLine("Tek Numaralar:");
foreach (var number in oddNumbers)
{
    Console.WriteLine($"{number}");
}

Sonuç:

Tek Numaralar:
1
3
5

Kodun Görünümü:

internal class Program
{
    private static void Main(string[] args)
    {
        var numbers = new List<int> { 1, 2, 3, 4, 5 };

        var evenNumbers = Filter(numbers, IsEven);

        Console.WriteLine("Çift Numaralar:");
        foreach (var number in evenNumbers)
        {
            Console.WriteLine($"{number}");
        }

        var oddNumbers = Filter(numbers, IsOdd);

        Console.WriteLine("Tek Numaralar:");
        foreach (var number in oddNumbers)
        {
            Console.WriteLine($"{number}");
        }
    }

    static List<int> Filter(List<int> numbers, Callback callback)
    { 
        var results = new List<int>();

        foreach (var number in numbers) 
        {
            if (callback(number))
            {
                results.Add(number);
            }
        }

        return results;
    }

    static bool IsOdd(int x) => x % 2 != 0;
    static bool IsEven(int x) => x % 2 == 0;
}

public delegate bool Callback(int x);

Bir temsilciyi callback olarak kullanarak, bir metodu başka bir metoda bağımsız değişken olarak iletebilirsiniz. Bu örnekte, Filter() metodu, tamsayı listesini filtrelemek için herhangi bir metodu kabul edebilen çok dinamik bir yapıya kavuşmuştur.

Bir Delegate’e Metot Ekleme

Bir delegate, birden çok metoda referans tutabilir. Bu durumda, delegate multicast delegate olarak adlandırılır.

Bir temsilciye metot eklemek için += operatörünü kullanırsınız. Örneğin:

delegate void Greeting(string message);

class Program
{
    static void SayHi(string name) => Console.WriteLine($"Hi {name}");

    static void SayBye(string name) => Console.WriteLine($"Bye {name}");
   
    static void Main(string[] args)
    {
        Greeting greeting = SayHi;
        greeting += SayBye;
        greeting("John");
    }
}

Sonuç:

Hi Fatih
Bye Fatih

Delegate’in, çağırma listesindeki metotları herhangi bir sırayla çağırabileceğini not etmek önemlidir. Bu nedenle, metotların sırasına güvenmemelisiniz.

Delegetler değişmez. Bu, bir delegate oluşturulduktan sonra değiştirilemeyeceği anlamına gelir. Bu nedenle, aşağıdakiler yeni bir delegate oluşturur ve onu greeting değişkenine atar:

greeting += SayBye;

Bir Delegate’den Metot Silme

Bir temsilciden bir metodu kaldırmak için -= operatörünü kullanırsınız. Boş bir çağrı listesiyle bir delegate çağırmaya çalışırsanız, C#’ın bir hata vereceğini unutmayın.

Aşağıdaki örnek, bir metodun bir delegate’in çağırma listesinden nasıl çıkarılacağını gösterir:

delegate void Greeting(string message);

class Program
{
    static void SayHi(string name) => Console.WriteLine($"Hi {name}");

    static void SayBye(string name) => Console.WriteLine($"Bye {name}");

    static void Say(string message) => Console.WriteLine(message);

    static void Main(string[] args)
    {
        Greeting greeting = SayHi;
        greeting += Say;
        greeting += SayBye;

        greeting -= SayHi;

        greeting("Fatih");
    }
}

Sonuç:

Fatih
Bye Fatih

Delegate Özet

  • Delegate, belirli bir parametre listesi ve dönüş türü olan metotlara başvuran bir türdür.
  • Bir metodu başka bir metoda bağımsız değişken olarak iletmek için callback olarak bir delegate kullanın.
  • Delegeler değişmez.
  • Bir delegate’in çağırma listesine bir metot eklemek için += operatörünü kullanın.
  • Bir metodu bir delegate’in çağırma listesinden kaldırmak için -= operatörünü kullanın.