четвртак, 16. јун 2016.

Delegati u C# programskom jeziku



Delegati su neka vrsta pokazivača na metode koji su objektno orjentisani i strogo tipizirani. Najjednostavnije rečeno delegat je referenca na metodu. Najlakše će te ih razumeti ukoliko zamislite da su delegati potpis metoda. Delegati vam omogućavaju da se logika vaše aplikacije u vašim metodama potpuno razdvoji od aplikacija koje su ih pozvale. Inače mnogi programeri ne shvataju zašto bi koristili delegate kad mogu pozvati metodu i ne vide njihovu svrhu. Delegati su predviđeni za situacije u kojima metodama želite da prenosite druge metode. Ja razumem da ste vi navikli da metodama prenosite podatke preko parametara ali ne i metode. Međutim postoje situacije u kojima će vaš metod umesto da za obradu podataka, poziva drugi metod i da bi situacija bila još komplikovanija vi čak i ne znate koji je taj drugi metod koji će se pozivati. Jer to možete znati jedino u fazi izvršavanja i zbog toga je neophodno pozivanje metode preko parametra i zato se koriste delegati.



( Delegati u C# programskom jeziku )

Delegati se često koriste kada radite sa nitima, klasama biblioteka i događajima. Delegate koje nameravate da koristite prvo treba da definišete. To u prevodu znači da vi definisanjem delegata saopštavate kompajleru koju vrstu metoda vaš delegat predstavlja. Svaki delegat se definiše unutar imenskog prostora ili klase. Zatim pravite jedan ili više primeraka tog delegata. Delegati mogu biti i sa i bez parametara. Sintaksa za delegata izgleda ovako; prvo se definiše delegat korišćenjem ključne reči delegate:

public delegate string ImeDelegata(string patrametar);

Delegat se može instancirati ovako:

public ImeDelegata mojDelegat = null;

Delegatu se može dodati referenca koristeći += operator:

mojDelegat += TestMetoda;

ili

mojDelegat = new ImeDelegata(TestMetoda);

Delegatu se takođe može ukloniti referenca koristeći -= operator:

mojDelegat -= TestMetoda;

Sve ovo vam može zvučati i izgledati nerazumljivo ali kad pogledate praktične primere upotrebe delegata, shvatićete koliko je to jednostavno. Ono što je najbitnije treba da razumete da se delegati izvršavaju dinamički; u toku izvršavanja; i da delegat može pokazivati na bilo koju metodu koja ima isti potpis kao i delegat. Pogledajte jednostavan primer kako se koristi delegat sa više metoda.

Primer upotrebe delegata

Samo radi primera, pretpostavimo da imamo dve jednostavne metode sa istim parametrom koje upisuju upis i ispis u neki sistem gostiju i evidentiraju vreme kad se ta aktivnost dogodila. Neki gosti se upisuju, neki se ispisuju jer su već u sistemu, neki se i upisuju i ispisuju dok se četvrti i upisuju i ispisuju ali beleže samo izlazak iz sistema. Da ne bismo komplikovali ovu proceduru sa pozivanjem metoda, idealno rešenje je u ovom slučaju delegat koji olakšava ceo proces. Inače nije neka svrha koristiti delegat ukoliko samo treba da pozovete jednom neku metodu.

using System;
using static System.Console;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SimpleDelegate
{
    class Program
    {
        delegate void Print(string patrametar);
        static public DateTime time;
        static void Main(string[] args)
        {
            Print guest1, guest2, guest3, guest4;
            string line = new String('-', 20);
                       
            guest1 = new Print(LogIn);
            guest2 = new Print(LogOut);
            guest3 = guest1 + guest2;
            guest4 = guest3 - guest1;

            WriteLine(Line + Environment.NewLine);

            WriteLine("Manuel Radovanovic is going to log in!" + Environment.NewLine);
            guest1("Manuel Radovanovic");
            WriteLine(line);

            WriteLine("Ella Napolis is going to log out!" + Environment.NewLine);
            guest2("Ella Napolis");
            WriteLine(line);

            WriteLine("Martine Moor is going to log in and log out!" + Environment.NewLine);
            guest3("Martine Moor");
            WriteLine(line);

            WriteLine("Charles Junger is going to log in and log out! But we need only time when loged out!" + Environment.NewLine);
            guest4("Charles Junger");
            WriteLine(line);

            WriteLine("Press any key to continue...");
            ReadKey();

        }

        static void LogIn (string name)
        {
            time = DateTime.Now;
            WriteLine(name + " is log in " + time + Environment.NewLine);

        }
        static void LogOut(string name)
        {
            time = DateTime.Now;
            WriteLine(name + " is log out " + time + Environment.NewLine);

        }
    }
}

Kao što vidite u kodu, definisanjem delegata i njegovih referenci mi zahvaljujući delegatu lako obavljamo upis i ispis gostiju. Naravno u pravom sistemu bi tražili od gostiju ime i lozinku dok bi se ispis pored konzole zapisivao u datoteku koja prati ulaz i izlaz u sistem. Upis i ispis odjednom gosta nam nebi ni trebao, ali ovde je to u primeru namerno stavljeno kako bi ste videli kako možete da manipuliše metodama kroz delegat. Kad pokrenete program, rezultat će biti sledeći:

--------------------

Manuel Radovanovic is going to log in!

Manuel Radovanovic is log in 6/15/2016 7:04:00 PM

--------------------

Ella Napolis is going to log out!

Ella Napolis is log out 6/15/2016 7:04:00 PM

--------------------

Martine Moor is going to log in and log out!

Martine Moor is log in 6/15/2016 7:04:00 PM

Martine Moor is log out 6/15/2016 7:04:00 PM

--------------------

Charles Junger is going to log in and log out! But we need only time when loged out!

Charles Junger is log out 6/15/2016 7:04:00 PM

--------------------

Press any key to continue...

Kako to sve izgleda možete pogledati i na video-u:



( C# 6.0 Tutorial - Advanced - 41. Simple Delegate )

Da li se delegati mogu koristiti radi filtriranja podataka?

Delegati se mogu koristiti u mnoge svrhe gde se traži upotreba više metoda. U nekim situacijama delegati su izuzetno korisni ali u nekim je možda bolje potražiti drugačiji pristup samog zadatka. To je uvek na programeru da proceni i testira kako mu je najbolje. Ali je jedno sigurno, u mnogim projektima će te često viđati upotrebu delegata i to u najkompleksnijim varijacijama programa. Sledeći primer pretpostavlja da imate neku vrstu filtriranja. Tada bi delegat mogao biti od koristiti na sledeći način:

using System;
using static System.Console;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace UsingDelegatForFiltering
{
    public struct Employee
    {
        public string Name;
        public double Salary;

    }

    class Program
    {
        public delegate bool FilterDelegate(Employee employee);

        static void Main(string[] args)
        {
            string line = new String('-', 20);

            Employee employee1;
            employee1.Name = "Manuel Radovanovic";
            employee1.Salary = 4500;

            Employee employee2;
            employee2.Name = "Ella Napolis";
            employee2.Salary = 3800;

            Employee employee3;
            employee3.Name = "Martine Moore";
            employee3.Salary = 1600;

            Employee employee4;
            employee4.Name = "Antoinete Amorros";
            employee4.Salary = 4200;

            Employee employee5;
            employee5.Name = "Charles Junger";
            employee5.Salary = 1200;

            List<Employee> employees = new List<Employee>() { employee1, employee2, employee3, employee4, employee5 };

            WriteLine("SALARIES:");
            WriteLine(line);
            DisplaySalaries("Minimum salaries:", employees, IsMinimum);
            WriteLine(line);
            DisplaySalaries("Median salaries:", employees, IsMedian);
            WriteLine(line);
            DisplaySalaries("High salaries", employees, IsHigh);
            WriteLine(line);



            WriteLine("Press any key to continue...");
            ReadKey();
        }

        static bool IsMinimum(Employee employee)
        {
            return employee.Salary < 1500;
        }

        static bool IsMedian(Employee employee)
        {
            return employee.Salary > 1500 & employee.Salary < 3000;
        }

        static bool IsHigh(Employee employee)
        {
            return employee.Salary > 3000;
        }

        static void DisplaySalaries(string title, List<Employee> employees, FilterDelegate filter)
        {
            WriteLine(title + Environment.NewLine);

            foreach (Employee employee in employees)
            {
                if (filter(employee))
                {
                    WriteLine($"{employee.Name}, {employee.Salary.ToString("C")}");

                }
            }

            WriteLine(Environment.NewLine);

        }
    }
}

Delegat u navedenom programu definitivno olakšava selekciju zaposlenih prema platama. Kad pokrenete program, rezultat će biti sledeći:

SALARIES:
--------------------
Minimum salaries:

Charles Junger, $1,200.00


--------------------
Median salaries:

Martine Moore, $1,600.00


--------------------
High salaries

Manuel Radovanovic, $4,500.00
Ella Napolis, $3,800.00
Antoinete Amorros, $4,200.00


--------------------
Press any key to continue...

Kako to sve izgleda možete pogledati i na video-u:


( C# 6.0 Tutorial - Advanced - 42. Using A Delegat For Filtering )