C# Delegate Kullanımı II - Generic Delegeler

C# Delegate Kullanımı I - Delege Nedir? yazımızda delege kavramını, ne işe yaradığını, nerelerde kullanıldığını incelemiştik.

C# generic delege tanımlama yapmamıza olanak sağlar. Örneğin, void döndüren ve bir parametre alan 2 metodumuz olsun: StringTarget; string tipinde parametre alıyor ve geriye void döndürüyor. IntTarget ise int tipinde parametre alıyor ve o da geriye void döndürüyor.

Normal şartlarda 2 delege tanımlamamız birine string parametresi diğerine int parametresi yazmamız gerekir. Şimdi ilk aklımıza gelen şekilde bu programı yazalım:

        delegate void MyStringDelegate(string args);
        delegate void MyIntDelegate(int args);

        static void Main(string[] args)
        {
            MyStringDelegate stringDelegate = new MyStringDelegate(StringTarget);
            MyIntDelegate intDelegate = new MyIntDelegate(IntTarget);

            stringDelegate("Safak");
            intDelegate(26);

            Console.ReadLine();
        }

        static void StringTarget(string arg)
        {
            Console.WriteLine("arg in uppercase is: {0}", arg.ToUpper());
        }
        static void IntTarget(int arg)
        {
            Console.WriteLine("++arg is: {0}", ++arg);
        }

Gördüğünüz gibi string tipinde parametre alan metodumuz için MyStringDelegate, int tipinde parametre alan metodumuz için ise MyIntDelegate delegesini tanımladık. Peki yine void döndüren fakat parametre olarak double alan bir metodu delege etmek istesek ne yapacağız? Bu durumda yeni bir MyDoubleDelegate yazmamız gerekecek. Bu durumu ortadan kaldırmak için şimdi bu programı birde generic delege kullanarak yazalım:

 
        //generic delegate
        delegate void MyGenericDelegate<T>(T args);

        static void Main(string[] args)
        {
            //generic delegate
            MyGenericDelegate<string> stringDelegate 
                = new MyGenericDelegate<string>(StringTarget);
            MyGenericDelegate<int> intDelegate 
                = new MyGenericDelegate<int>(IntTarget);

            stringDelegate("Safak");
            intDelegate(26);

            Console.ReadLine();
        }

        static void StringTarget(string arg)
        {
            Console.WriteLine("arg in uppercase is: {0}", arg.ToUpper());
        }
        static void IntTarget(int arg)
        {
            Console.WriteLine("++arg is: {0}", ++arg);
        }

Gördüğünüz gibi delegate void MyGenericDelegate<T>(T args); generic delege tanımı yaparak Hem StringTarget hemde IntTarget metodlarını saklayabildik. Bundan sonra double paramere alan geriye void döndüren bir fonksiyon yazsakta yeni bir delege tanımı yapmamıza gerek kalmayacak, MyGenericDelegate üzerinden nesne örneği oluşturup T yerine double vererek bunu gerçekleştirebiliriz.

Çıktı:



Action<> ve Func<> Kullanımı:

Normal şartlarda delege kullanmamız için şu adımları gerçekleştirmemiz gerekiyor:
* İçinde saklayacağı metot formatına uygun custom delege tanımı yapmak
* Bu custom delegeden bir nesne örneği oluşturmak
* Oluşturduğumuz nesne üzerinden Invoke işlemini gerçekleştirmek
Action<> ve Func<> kısa bir şekilde delege tanımı yapmamıza olanak sağlıyor.

Action<> Kullanımı:

Geriye void döndüren metodları tutan delegeleri kısa yoldan tanımlamamızı sağlar.

        static void Main(string[] args)
        {
            Action<string, int> action
                      = new Action<string, int>(DisplayAge);
            action("Safak", 26);
        }

        static void DisplayAge(string fullName, int age)
        {
            Console.WriteLine(fullName + " : " + age);
        }

Gördüğünüz gibi delege tanımı yapmadan DisplayAge metodu saklandı ve Invoke edilebildi. Bir kez daha söylemekte fayda var Action<> geri değer döndürmez.

Func<> Kullanımı:

Action<> 'ın geri değer döndürebilen halidir. Son parametre dönüş değer tipini belirtir. Örnek kullanım:

        static void Main(string[] args)
        {
            Func<DateTime, double> func 
                 = new Func<DateTime, double>(GetUserAgeAtTime);
            double dateDif = func(DateTime.Now.AddYears(-2));
            Console.WriteLine("\nDate Dif: {0}", dateDif);

            Console.ReadLine();
        }

        static double GetUserAgeAtTime(DateTime birthDate)
        {
            return (DateTime.Now - birthDate).TotalDays;
        }

Yukarıdaki örnekte <DateTime, double> şeklinde yazılmıştır. DateTime parametrenin tipini double ise dönüş değer tipini belirtir.

Örnek ProjelerGenericDelegateExample.rar ,  ActionFuncExample.rar

3 yorum :

  1. Teşekürler sade ve güzel bir anlatım

    YanıtlaSil
  2. bir kaç yerde okuduğum ama anlamadığım bir konuyu çok yalın ve anlaşılır bir şekilde ortaya koşmuşsunuz. elinize sağlık.

    YanıtlaSil
  3. Güzel bir anlatım, tebrik ediyorum. Diğer sayfalardaki gibi karışık ve ezbere bir anlatım yerine mantığını kavratmaya yönelik bir anlatım olmuş

    YanıtlaSil