Cześć,

w dzisiejszym poście chciałbym poruszyć temat Delegat w języku C#.

 

Z językiem C# bardzo ścieśle sa powiązane Delegaty. Delegaty są bardzo często porównywane do wskaźników na funkcje znanych z języka C++. Oferują bardzo podobną funkcjonalność, jednak są o wiele bezpieczniejsze i udostępniają większe możliwości. Zapewniają kontrolę typów oraz wywołania asynchroniczne metod.

Delegaty to referencyjny typ danych, który przechowuje referencje do metody. Referencja ta może być zmieniana w trakcie wykonywania programu.

Delegaty są przede wszystkim wykorzystywane do implementacji zdarzeń oraz wywołań zwrotnych metod(call-back). Czym są wywołania zwrotne? Programista rejestruje metodę do późniejszego wywołania, natomiast biblioteka wywołuje ją w stosownym dla siebie czasie. Wszystkie delegaty niejawnie dziedziczą z klasy System.Delegate.

Krótka książkowa definicja, mówiąca czym jest delegat:

Delegaty to obiekty, które wskazują na dowolne metody znajdujące się w programie. Są definiowane za pomocą słowa kluczowego delegate. Przypominają działanie wskaźników z języka C++, jednak zapewniają kontrolę typów. Mogą wskazywać metody instancyjne oraz statyczne.

Po co są potrzebne delegaty?

Na jednych z wykładów na uczelni, wykładowca zwrócił uwagę, że generalizując problem używania wskaźników na funkcje istnieje od od wielu lat, głównie z czasów  gdzie prym wiodły języki C/C++.
Często, gęsto problem pojawiał się w momencie projektowania przeróżnych ale za to bardzo rozbudowanych systemy bądź aplikacji, kiedy to zaistniała potrzeba, aby funkcja wywoływana mogła komunikować się z funkcją wywołującą.

Wskaźniki na funkcje mogą być argumentami metod, dzięki temu do funkcji można przesłać adresy różnych funkcji zależnie od wymaganej sytuacji lub wyboru użytkownika.

Taką samą elastyczność zapewniają delegaty w języku C#.

Podążając za tropem dochodzimy do tematu funkcji wywołań zwrotnych (nic innego jak callbacks). Znane przede wszystkim z C++ callbacki są po prostu wskaźnikami na funkcję, więc ich odpowiednikiem jest delegata w C#.

Idąc dalej tym tropem dochodzimy do tematu funkcji wywołań zwrotnych (callbacks). Znane przede wszystkim z C++ callbacki są po prostu wskaźnikami na funkcję, więc ich odpowiednikiem jest delegata w C#.

 

Czym są callbacks?

Callbacki to nic innego jak odwrotne użycie zwykłych funkcji. 

Posiadając dowolną metodę, programista zajmuje się jej wywołaniem względem instancji danej klasy. Dzięki użyciu callbacków sytuacja się odwraca. Programista nie potrzebuje umieszczać w kodzie manualnego wywołania funkcji, a jedynie definiuje funkcję o odpowiedniej nazwie i parametrach, do późniejszego wywołania przez inne elementy systemu (niezależne od naszego programu).

Taki mechanizm był nierozłączny podczas np. współpracy z API Win32  ( od and. Application Programming Interface) z programami pisanymi pod Windowsa. Posługując się wskaźnikami na funkcje oraz callbackami, funkcje API Windowsa nie miały narzuconego wywołania konkretnej metody – mogły wywoływać wskaźnik na funkcję, a funkcję dopisywał na własną rękę programista.

Jest to bardzo elastyczne rozwiązanie. Dokładnie taki sam mechanizm zapewnia nam język C# w postaci delegat – mimo, że jest to język wysokiego poziomu i komunikacja z API Win32 nie jest już potrzebna.

 

Nie tylko API Windowsa

Należy przy tym pamiętać aby tego typu zastosowanie, nie wiązać bezpośrednio tylko z funkcjami API Windowsa. Delegat jest wskaźnikiem na dowolną funkcję lub metodę.

 

Niejednokrotnie ich użycie może przyczynić się do znacznej optymalizacji kodu naszego programu. Wszystko zależy od sytuacji.

 

Budowa delegatów

Delegaty to obiekty dziedziczące niejawnie lecz bezpośrednio z MulticastDelegate. Ta z kolei dziedziczy z klasy Delegate oraz Object.

 

Deklarując nowy delegat kompilator automatycznie przekształca go na klasę. 

Klasa ta jest automatycznie zaplombowana czyli sealed a więc nie można z niej dziedziczyć. Automatycznie są także generowane niektóre metody. Oto lista najważniejszych metod każdego delegata:

Invoke() – wywołuje metody podpięte do delegata (jedną lub listę metod). Przyjmuje takie same argumenty jak metoda związana z delegatem. Działa synchronicznie względem głównego wątku programu.

BeginInvoke() – wywołuje metody związane z delegatem w sposób asynchroniczny. Wywołana metoda zostanie wykonana w osobnym wątku.

 

Delegaty w języku C# zapewniają bardzo wygodę a przede wszystkim umożliwiają asynchroniczne wywoływania metod. Jest to w wielu sytuacjach główna przyczyna używania w danym momencie delegata zamiast zwykłego wywołania funkcji.

 


Ale ok, teoria – teorią, ale zerknijmy jak delegaty zachowują się w kodzie.

 

Składnia:

Deklarowanie delegatów

Deklaracja delegatu określa metody, które mogą być wywołane za jego pomocą. Delegat może się odnosić do metody, która ma taką samą sygnaturę jak delegat.
przykład:

Poniższy przykład pokazuje deklaracje, utworzenie instancji oraz użycie delegata, który może mieć referencje do metody przyjmującej liczbę całkowitą oraz zwracającej liczbę całkowitą:

Delegaty złożone

Nasze Delegaty mogą być łączone. Łączymy je za pomocą operatora (+). Delegat złożony wywołuje dwa delegaty tak jakby były złączone. Przy tym pamiętajmy że tylko delegaty tego samego typu mogą być ze sobą złożone. Natomiast operator (-) może być użyty do usunięcia danego delegatu z delegata złożonego.

 

Korzystając z tej właściwości delegatów można utworzyć listę delegatów, które zostaną wywołane, w momencie wywołania delegatu złożonego. Operacja taka to tzw. multicasting. Poniższy program pokazuje przykład wykorzystania takiej operacji:

 

Przykład:

Jak zawsze kod wrzucony będzie do GitHuba.

Podobało się? dajcie like’a 😉 lub piszcie i komentujcie.

Post Author: Csharpowe Zmagania

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *

This site uses Akismet to reduce spam. Learn how your comment data is processed.