Pobieranie prezentacji. Proszę czekać

Pobieranie prezentacji. Proszę czekać

Waldemar Bartyna 1 Programowanie zaawansowane Delegaty.

Podobne prezentacje


Prezentacja na temat: "Waldemar Bartyna 1 Programowanie zaawansowane Delegaty."— Zapis prezentacji:

1 Waldemar Bartyna 1 Programowanie zaawansowane Delegaty

2 Waldemar Bartyna Plan wykładu 1.Delegaty 2.Zdarzenia 3.Metody anonimowe 4.Operator lamda 2

3 Waldemar Bartyna 3 Delegaty

4 Waldemar Bartyna Spojrzenie w przeszłość W Windows API często korzystano ze wskaźników do funkcji w celu tworzenia elementów zwanych funkcjami wywołań zwrotnych, albo po prostu wywołaniami zwrotnymi (ang. callback). Stosowanie tego mechanizmu pozwalało programistom na konfigurowanie wybranej funkcji tak, aby była ona w stanie wywoływać inne, dynamicznie przekazywane, funkcje. Przy pomocy tego podejścia radzono sobie z obsługą kliknięcia przycisku, poruszenia myszką, wyboru opcji z menu i innymi przykładami dwukierunkowej komunikacji między dwoma bytami programistycznymi. 4

5 Waldemar Bartyna Spojrzenie w przeszłość c. d. Standardowe funkcje wywołań zwrotnych (rodem z języka C) reprezentują jedynie adres w pamięci. Wywołania zwrotne mogłyby zawierać informacje związane z bezpieczeństwem typów, takie jak ilość i typ parametrów oraz typ zwracanej wartość przez metodę, na którą wskazują. Z powodu braku tych informacji, standardowe wywołania zwrotne były często przyczyną błędów i zawieszania się aplikacji. Nie zmienia to faktu, że sam mechanizm wywołań zwrotnych jest bardzo użyteczny. 5

6 Waldemar Bartyna Powrót w przyszłość Na platformie.NET, stosowanie wywołań zwrotnych jest nadal możliwe, a ich funkcjonalność została zrealizowana w bardziej bezpieczny i obiektowo zorientowany sposób. Delegat to obiekt zapewniający bezpieczeństwo typu, wskazujący na metodę (lub zbiór metody), które mogą być wywołane w późniejszym czasie. Delegat przechowuje następujące informacje:  Adres metody, którą może wywołać,  Ilość i typ argumentów metody,  Typ wartości (lub jej brak) zwracanej przez daną metodę. 6

7 Waldemar Bartyna Cechy delegatów W odróżnieniu od wskaźników do funkcji w C i C++, delegaty mogą wskazywać na statyczne i instancyjne metody. Po stworzeniu delegata i dostarczeniu potrzebnych informacji, może on dynamicznie wywoływać metody, przekazywane do niego w czasie wykonania programu. Każdy delegat jest automatycznie wyposażany w możliwość wywoływania metod w sposób synchroniczny i asynchroniczny. Upraszcza to w dużym stopniu wywoływanie metod w drugoplanowym wątku, bez konieczności tworzenia i utrzymywania obiektu wątku. 7

8 Waldemar Bartyna Definiowanie delegata Delegaty tworzymy za pomocą słowa kluczowego delegate. Możemy mu nadać dowolną nazwę. Definiowany delegat musi odpowiadać sygnaturze metod, które ma przechowywać. Na przykład, chcąc stworzyć delegat o nazwie BinaryOp, który może wskazywać na dowolną metodę przyjmującą dwa parametru typu int i zwracającą typ int, zapiszemy następującą definicję: 8

9 Waldemar Bartyna Klasy związane z delegatami Kompilator C#, przetwarzając definicję delegata, automatycznie generuje klasę dziedziczącą po klasie System.MulticastDelegate. Klasa ta, razem z bazową klasą System.Delegate, zapewnia wymaganą infrastrukturę pozwalającą delegatom na przechowywanie listy metod do późniejszego wywołania. 9

10 Waldemar Bartyna Klasy związane z delegatami c. d. Wygenerowana przez kompilator klasa posiada trzy metody:  Metoda Invoke() służy do wywoływania każdej z metod przechowywanych w delegacie w sposób synchroniczny (wywołujący musi poczekać na zakończenie się wywoływanej metody). Metoda ta jest wywoływana niejawnie.  Metody BeginInvoke() i EndInvoke() powalają na wywołanie metody w sposób asynchroniczny w osobnym wątku wykonania.  Najczęstszym powodem korzystania z wątku jest przerzucenie do niego wykonania funkcji zajmującej dużo czasu. Dzięki delegatom, mamy taką możliwość bez ręcznego tworzenia obiektu wątku. 10

11 Waldemar Bartyna Jak kompilator generuje klasę delegata? Parametry i wartość zwracana przez metodę Invoke() dokładnie odpowiadają definicji delegata. Parametry metody BeginInvoko() odpowiadają parametrom delegata, Oprócz nich, metoda ta zawsze przyjmuje dwa dodatkowe parametry (AsyncCallback i object) w związku z asynchronicznym wywołaniem. Wartość zwracana przez metodę EndInvoke() odpowiada tej zdefiniowanej w delegacie. Dodatkowo przyjmuje pojedynczy parametr – obiekt klasy implementującej interfejs IAsyncResult. 11

12 Waldemar Bartyna Jak kompilator generuje klasę delegata? c. d. 12 W kolejnym przykładzie, załóżmy, że chcemy zdefiniować delegat, który może przechowywać i wywoływać metody zwracające obiekt klasy System.String i przyjmujące trzy argumenty typu System.Boolean.

13 Waldemar Bartyna Jak kompilator generuje klasę delegata? c. d. 2 Delegaty mogą również wskazywać na metody przyjmujące dowolną liczbę parametrów z atrybutami ref i out. Dwie pierwsze metody zostały wygenerowane zgonie z poprzednimi przykładami. Różnica polega na tym, że metoda EndInvoke() została rozszerzona o parametry z atrybutami ref i out. 13

14 Waldemar Bartyna Ogólna zasada generowania klasy delegata Zasadę tą obrazuje następujący pseudo kod: 14

15 Waldemar Bartyna Klasa System.Delegate 15 Klasa bazowa System.Delegate posiada, między innymi, następujące składowe.

16 Waldemar Bartyna Klasa System.MulticastDelegate Każda klasa wygenerowana przez kompilator dziedziczy po klasie System.MulticastDelegate. 16

17 Waldemar Bartyna Wspólne składowe delegatów W swoim kodzie, nie możemy dziedziczyć po tych dwóch klasach. Powoduje to błąd kompilacji. Jednakże, używając słowa kluczowego delegate, pośrednio tworzymy klasę dziedziczącą po System.MulticastDelegate. Kilka składowych wspólnych dla wszystkich delegatów to:  Method – Właściwość ta zwraca obiekt klasy System.Reflection.MethodInfo, która reprezentuje szczegółowe informacje o metodzie przechowywanej przez delegata.  Target – Właściwość ta zwraca informację o typie, w którym została zdefiniowana przechowywana metoda, jeżeli jest ona zdefiniowana na poziomie obiektu. W przeciwnym razie zwraca null, co oznacza, że jest to metoda statyczna. 17

18 Waldemar Bartyna Wspólne składowe delegatów c. d.  Combine() – Ta statyczna metoda dodaje wskazaną metodę do listy przechowywanej przez delegata. W C# metoda ta jest wyzwalana przez użycie przeładowanego operatora +=.  GetInvocationList( ) – Metoda ta zwraca tablicę obiektów typu System.Delegate, reprezentujących poszczególne metody do wywołania.  Remove(), RemoveAll() – Te statyczne metody usuwają wskazaną metodę (lub wszystkie) z listy wywołań delegata. 18

19 Waldemar Bartyna Najprostszy przykład użycia delegata 19

20 Waldemar Bartyna Najprostszy przykład użycia delegata c. d. W przykładzie zdefiniowaliśmy delegata, który może wskazywać na metody przyjmujące dwa parametry liczbowe i zwracające liczbę. Nazwy metod są nieistotne. Jeżeli chcemy umieścić docelową metodę w delegacie, po prostu przekazujemy ją poprzez konstruktor. Metodę, na którą wskazuje nasz delegat wywołujemy w sposób przypominający bezpośrednie wywołanie funkcji. W rzeczywistości, wywoływana jest niejawnie metoda Invoke(). Możemy równie dobrze wywołać ją jawnie. 20

21 Waldemar Bartyna Najprostszy przykład użycia delegata c. d. 2 Delegaty na platformie.NET zapewniają bezpieczeństwo typów. Dlatego też próba przekazania do delegata metody nie odpowiadającej zadanemu wzorcowi (sygnaturze metody) spowoduje wyświetlenie błędu podczas kompilacji. Załóżmy, że klasa SimpleMath posiada jeszcze jedną metodę. Próba przekazania jej do delegata spowoduje błąd w czasie kompilacji (metoda nie odpowiada sygnaturze delegata). 21

22 Waldemar Bartyna Pozyskiwanie informacji o metodach Metoda wyświetlająca informacje o metodach przechowywanych w podanym delegacie. Po odpowiedniej zmianie metody main() w naszym przykładzie, otrzymamy następujący rezultat. Dlaczego? 22

23 Waldemar Bartyna Pozyskiwanie informacji o metodach c. d. Po zmianie metod ze statycznych na wywoływane z poziomu instancji, nadal możemy przekazywać je do delegata. Informacje o metodzie instancyjnej zawierają informacje o typie, w którym zostały zdefiniowane (właściwość Target). 23

24 Waldemar Bartyna Dodanie delegatów do klasy Car Aby zastąpić komunikację z klasą Car za pomocą interfejsów wywołań zwrotnych na delegaty należy:  Zdefiniować nowy typ delegata, który wyśle powiadomienie do wywołującego,  Zadeklarować w klasie Car zmienne odpowiednich typów delegatów,  Stworzyć funkcje pomocnicze, które pozwolą wywołującemu na przekazanie metod do zadeklarowanych zmiennych (delegatów),  Zaktualizować metodę Accelerate(), tak aby wywoływała metody na liście delegata w odpowiedniej sytuacji. 24

25 Waldemar Bartyna Dodanie delegatów do klasy Car c. d. 25

26 Waldemar Bartyna Dodanie delegatów do klasy Car c. d. 2 26

27 Waldemar Bartyna Dodanie delegatów do klasy Car c. d. 3 27

28 Waldemar Bartyna Multicasting Aby zapewnić możliwość rejestrowania wielu metod w jednej zmiennej delegata (i tym samym możliwość wywoływania wielu metod jednocześnie – ang. multicasting), należy odpowiednio zmienić implementację metod pomocniczych. Poprzez użycie przeładowanego operatora +=, wywołują one metodę Combine() dołączając wskazaną metodę do listy wywołań delegata. 28

29 Waldemar Bartyna Multicasting c. d. 29

30 Waldemar Bartyna Usunięcie metody z listy wywołań Aby wywołujący mógł usunąć metodę z listy wywołań, należy dostarczyć odpowiednie metody pomocnicze. Korzystają one z przeładowanego operatora -=, który powoduje niejawne wywołanie metody Remove(). 30

31 Waldemar Bartyna Usunięcie metody z listy wywołań c. d. W poniższym przykładzie usunięcia metody, pamiętamy zmienną delegata, którą później przekazujemy do usunięcia. Możliwe jest również ponowne zdefiniowania delegata na bazie metody, którą chcemy usunąć z listy. Tak więc przetrzymywanie zmiennej z takim delegatem nie jest konieczne. 31

32 Waldemar Bartyna Bardziej złożony przykład 32 Tradycyjnie zaczynamy od odpowiedniej modyfikacji klasy Car.

33 Waldemar Bartyna Bardziej złożony przykład c. d. Do klasy Car dodajemy również definicję kolejnego typu delegata. CarMaintenanceDelegate może przechowywać i wywoływać dowolną metodę przyjmującą jako parametr obiekt klasy Car i nie zwracającą żadnej wartości. 33

34 Waldemar Bartyna Bardziej złożony przykład c. d. 2 Dodajemy definicję klasy, przechowującej listę samochodów za pomocą kolekcji generycznej. Na kolejnym slajdzie znajduje się definicja metody tej klasy, która jako argument przyjmuje wskazany typ delegata. 34

35 Waldemar Bartyna Bardziej złożony przykład c. d. 3 35

36 Waldemar Bartyna Bardziej złożony przykład c. d Dodajemy klasę definiującą metody, które będą przechowywane i wywoływane przez delegata klasy Car.

37 Waldemar Bartyna Bardziej złożony przykład c. d. 5 Garaż deleguje całą pracę do działu obsługi 37

38 Waldemar Bartyna Bardziej złożony przykład c. d. 6 38

39 Waldemar Bartyna Kowariancja delegatów Do tej pory, przykładowe delegaty zwracały proste wartości liczbowe. Mogą one również zwracać złożone klasy należące do różnych hierarchii dziedziczenia. Załóżmy, że mamy klasę Car i dziedziczącą po niej klasę SportsCar. Utwórzmy delegat, który wywołuje utworzenie obiektu. 39

40 Waldemar Bartyna Kowariancja delegatów c. d. 40

41 Waldemar Bartyna Kowariancja delegatów c. d. 2 41

42 Waldemar Bartyna Kowariancja delegatów c. d. 3 Kowariancja pozwala na przekazywanie do delegata metod, których typ zwracanej wartości nie jest identyczny z sygnaturą delegata, ale jest potomnym w stosunku do zwracanego typu zdefiniowanego w tym delegacie. Na podobnej zasadzie działa kontrkowariancja, z tym, że dotyczy ona argumentów metod przekazywanych do delegata. 42

43 Waldemar Bartyna Generyczne delegaty 43

44 Waldemar Bartyna Generyczne delegaty c. d. 44

45 Waldemar Bartyna 45 Zdarzenia

46 Waldemar Bartyna Niedogodności związane z delegatami Delegaty są konstrukcjami umożliwiającymi dwukierunkową komunikację między obiektami w pamięci. Jednak wykorzystywanie ich w surowej postaci pociąga za sobą kilka niedogodności. Aby posłużyć się delegatem musimy:  Zdefiniować typ delegata,  Zadeklarować potrzebne zmienne tego typu,  Stworzyć własne metody pomocnicze pozwalające na rejestrowanie i wyrejestrowywanie metod z delegatów w celu zachowania hermetyzacji. W przypadku zadeklarowania zmiennej delegata jako publicznej, ryzykujemy możliwości manipulacji na liście wywołań przez potencjalnie niebezpieczny kod w obiektach korzystających z naszego delegata. 46

47 Waldemar Bartyna Słowo kluczowe event Rozwiązaniem tych niedogodności jest słowo kluczowe event. Gdy kompilator napotka na to słowo, automatycznie generuje metody do rejestracji i wyrejestrowywania metod oraz zmienną do przechowywania listy tych metod. Zmienne te są zawsze deklarowane jako prywatne. W sumie, słowo kluczowe event (zdarzenie) jest po prostu syntaktycznym skrótem, który oszczędza czas programiście (podobnie jak w przypadku właściwości automatycznych). 47

48 Waldemar Bartyna Definiowanie zdarzenia Definiowanie zdarzenia to dwukrokowy proces: –Najpierw definiujemy odpowiedni typ delegata, –Następnie definiujemy zdarzenie skojarzone z tym delegatem. 48

49 Waldemar Bartyna „Odpalanie” zdarzeń 49

50 Waldemar Bartyna Rejestracja metod obsługujących zdarzenie 50

51 Waldemar Bartyna Korzystajmy z pomocy środowiska Przy dodawaniu metod do zdarzeń możemy skorzystać z pomocy środowiska. Po wpisaniu operatora +=, system pomocy podpowiada nam, jakiego rodzaju delegat jest obsługiwany przez dane zdarzenie. Po kliknięciu tabulatora, system pomocy doda odpowiedni konstruktor i teraz z kolei proponuje nam nazwę metody obsługującej dane zdarzenie. Jeżeli ponownie wciśniemy tabulator, zostanie wygenerowany szkielet metody o proponowanej nazwie. 51

52 Waldemar Bartyna Wzorzec zdarzenia Zdarzenia w bibliotece klas bazowych.NET definiowane są zgodnie ze wspólnym standardem. Delegaty przez nie obsługiwane przyjmują zawsze dwa parametry:  Pierwszym jest System.Object reprezentujący referencje do obiektu, który wywołał dane zdarzenie.  Drugi dziedziczy po typie System.EventArgs i reprezentuje informacje o aktualnym zdarzeniu. 52

53 Waldemar Bartyna Wzorzec zdarzenia c. d. W przypadku prostych zdarzeń można bezpośrednio przekazać obiekt klasy EventArgs. W innych przypadkach należy stworzyć własną klasę dziedziczącą po klasie EventArgs. 53

54 Waldemar Bartyna Wzorzec zdarzenia c. d. 2 Obecnie, definicja naszego delegata będzie wyglądać następująco: Odpalenie zdarzenia związanego z powyższym delegatem 54

55 Waldemar Bartyna Strona wywołującego I odpowiednio dopasowujemy metody obsługujące zdarzenia po stronie wywołującego. 55

56 Waldemar Bartyna Generyczny delegat EventHandler Skoro tyle delegatów przyjmuje jako parametr obiekt klasy System.Object oraz potomka klasy EventArgs, możemy jeszcze bardziej uprościć nasz kod poprzez wykorzystanie generycznego delegata EventHandler, gdzie T jest niestandardową klasą dziedziczącą po EventArgs. 56

57 Waldemar Bartyna Generyczny delegat EventHandler c. d. 57

58 Waldemar Bartyna 58 Metody anonimowe i operator lambda

59 Waldemar Bartyna Problem Metody służące do obsługi zdarzeń nie są przeważnie wykorzystywane w innym miejscu aplikacji. 59

60 Waldemar Bartyna Rozwiązanie 60

61 Waldemar Bartyna Metody anonimowe Możliwe jest powiązanie delegata bezpośrednio z blokiem kodu w momencie rejestracji obsługi zdarzenia. Taki blok kodu jest nazywany metodą anonimową. Składnia metody anonimowej wygląda następująco: Z metody anonimowej mamy dostęp do zewnętrznych zmiennych (oprócz zmiennych oznaczonych atrybutem ref i out. 61

62 Waldemar Bartyna Konwersja grup metod Kompilator obsługuje również konwersję grup metod. Dzięki niej możemy do zdarzenia dodać od razu nazwę metody obsługującej dane zdarzenie (bez koniczności tworzenia delegata). W razie konieczności, samą nazwę metody można rzutować na odpowiedni typ delegata. 62

63 Waldemar Bartyna Operator lambda Operator lamba (=>) pozwala jeszcze bardziej skrócić zapis metod anonimowych. 63

64 Waldemar Bartyna Operator lambda c. d. Przed samym operatorem podajemy listę argumentów (typy są nieobowiązkowe) w nawiasach. W przypadku bezargumentowej metody wstawiamy przed operatorem same nawiasy: (() => … ). Po operatorze, umieszczamy blok instrukcji do wykonania, np.: 64

65 Waldemar Bartyna 65 Dziękuję za uwagę


Pobierz ppt "Waldemar Bartyna 1 Programowanie zaawansowane Delegaty."

Podobne prezentacje


Reklamy Google