Waldemar Bartyna 1 Programowanie zaawansowane Strukturalna obsługa wyjątków.

1 [email protected] Waldemar Bartyna 1 Programowanie zaa...
Author: Irena Rakowiecki
0 downloads 0 Views

1 [email protected] Waldemar Bartyna 1 Programowanie zaawansowane Strukturalna obsługa wyjątków

2 [email protected] Waldemar Bartyna Pytania egzaminacyjne (Zestaw01) 1.Co to jest takiego ta cała platforma.NET? 2.Jakie są jej najważniejsze cechy? 3.Jakie elementy składają się na platformę.NET? 4.Co to jest CLR? 5.Co to jest CTS? 6.Co to jest CLS? 7.Co to jest CIL? 8.Co to jest CLI? 2

3 [email protected] Waldemar Bartyna Pytania egzaminacyjne (Zestaw02) 9.Co to są pakiety? 10.Co to są typy i co do nich zaliczamy? 11.Jaka jest zależność między pakietami, przestrzeniami nazw i typami? 12.W jaki sposób wykonywane są programy na platformie.NET? 3

4 [email protected] Waldemar Bartyna Pytania egzaminacyjne (Zestaw03) 13.Na czym polega OOP i jakie są jego trzy podstawowe filary? 14.Na czym polega dziedziczenie? 15.Do czego wykorzystujemy słowa kluczowe protected, base, sealed? 16.Na czym polega agregacja? 17.Na czym polega zagnieżdżanie? 18.Na czym polega delegacja? 4

5 [email protected] Waldemar Bartyna Pytania egzaminacyjne (Zestaw04) 19.Na czym polega polimorfizm? 20.Co to są abstrakcyjne klasy bazowe? 21.Co to jest interfejs polimorficzny? 22.Na czym polega nadpisywanie i zasłanianie składowych? 5

6 [email protected] Waldemar Bartyna B. z M. 1 6

7 [email protected] Waldemar Bartyna B. z M. 2 7

8 [email protected] Waldemar Bartyna B. z M. 3 8

9 [email protected] Waldemar Bartyna B. z M. 4 9

10 [email protected] Waldemar Bartyna B. z M. 5 10

11 [email protected] Waldemar Bartyna B. z M. 6 11

12 [email protected] Waldemar Bartyna B. z M. 7 12

13 [email protected] Waldemar Bartyna B. z M. 8 13

14 [email protected] Waldemar Bartyna Ciekawostek 14

15 [email protected] Waldemar Bartyna Strukturalna obsługa wyjątków 1.Główna klasa nadrzędna 2.Strukturalna obsługa wyjątków 15

16 [email protected] Waldemar Bartyna 16 Główna klasa nadrzędna System.Object

17 [email protected] Waldemar Bartyna Zagadka Co jest klasą nadrzędną naszej klasy bazowej Car, Employee, Shape? 17 W świecie.NET każda klasa jest pochodną (bezpośrednio lub pośrednio) klasy bazowej System. Object.

18 [email protected] Waldemar Bartyna Główna klasa nadrzędna Klasa Object definiuje zbiór składowych wspólny dla wszystkich języków platformy.NET Jeżeli definiujemy klasę nie podając jawnie jej klasy bazowej, kompilator automatycznie traktuje ją jako pochodną klasy Object. Możemy to sami jawnie zapisać podczas definiowania klasy 18

19 [email protected] Waldemar Bartyna Definicja klasy Object 19

20 [email protected] Waldemar Bartyna Metoda wirtualna Equals() Domyślnie, metoda ta zwraca wartość true tylko wtedy, gdy porównywane elementy odnoszą się do tego samego miejsca w pamięci Oznacza to, że służy ona do porównywania referencji, a nie stanów obiektów. Z reguły jest przesłaniana tak, że zwraca true wtedy, gdy porównywane obiekty mają takie same wewnętrzne wartości stanu (semantyka na bazie wartości). Gdy przesłaniamy tę metodę, należy również przesłonić metodę GetHashCode() (obie te metody są używane wewnętrznie przez typ Hashtable podczas pobierania obiektów z kolekcji. 20

21 [email protected] Waldemar Bartyna Składowe klasy System.Object GetHashCode() – zwraca wartość typu int, która identyfikuje daną instancję klasy Object GetType() – zwraca obiekt klasy Type, który szczegółowo opisuje wskazany obiekt. Jest to metoda identyfikacji typów w czasie wykonania dostępna dla wszystkich obiektów (Runtime Type Identification – RTTI). Finalize() – metoda ta jest wywoływana w celu zwolnienia wszystkich zaalokowanych zasobów przed zniszczeniem obiektu. 21

22 [email protected] Waldemar Bartyna Składowe klasy System.Object (c. d.) ToString() – zwraca wartość typu string reprezentującą dany obiekt. o Reprezentacja ta ma format. (nazywany ją pełną nazwą kwalifikowaną – ang. fully qualified name). o Metoda ta może być (i często jest) przesłaniana przez klasy pochodne, które za jej pomocą zwracają łańcuch znaków zawierający opis wewnętrznego stanu obiektu (najczęściej w postaci par: nazwa pola, wartość). MemberwiseClone() – metoda ta zwraca klon obiektu (kopiowana jest każda jego skłądowa). 22

23 [email protected] Waldemar Bartyna Wywołanie metod domyślnych 23

24 [email protected] Waldemar Bartyna Wynik wywołania 24 Domyślna implementacja metody ToString() zwraca pełną nazwę kwalifikowaną. Każdy projekt w C# definiuje główną przestrzeń nazw o domyślnej nazwie identycznej z nazwą projektu. W niej umieszczona została klasa Person. Domyślne zachowanie metody Equals() polega na sprawdzeniu, czy podane zmienne wskazują na tą samą instancję klasy (na to samo miejsce w pamięci).

25 [email protected] Waldemar Bartyna Dodanie pól danych Uzupełniamy naszą przykładową klasę o pola reprezentujące jej stan wewnętrzny 25

26 [email protected] Waldemar Bartyna Nadpisanie System.Object.Tostring() Wiele klas nadpisuje metodę ToString(); ułatwia to testowanie aplikacji i nie tylko Metodę tą można implementować w dowolny sposób, ale przyjęty standard to oddzielanie nazwy pola i jego wartości dwukropkiem oraz zamknięcie opisu w nawiasy kwadratowe. 26

27 [email protected] Waldemar Bartyna Nadpisanie System.Object.Tostring() (c. d.) Należy pamiętać, że właściwa implementacja metody ToString() powinna uwzględniać wszystkie dane zdefiniowane w łańcuchu dziedziczenia. Gdy nadpisujemy metodę ToString() dla klasy rozszerzającej niestandardową klasę bazową, pierwszym krokiem powinno być pozyskanie wyniku działania metody ToString() z klasy nadrzędnej. Kolejnym krokiem jest dodanie opisu informacji specyficznych dla klasy pochodnej. 27

28 [email protected] Waldemar Bartyna Nadpisanie System.Object.Equals() 28 Sposób porównania obiektów ma bazować na porównaniu ich wewnętrznych stanów.

29 [email protected] Waldemar Bartyna Nadpisanie System.Object.Equals() 2 29 W tej implementacji, metoda Equals() zwraca wartość true tylko wtedy, gdy dwa porównywane obiekty zawierają te same wartości stanu (a nie wskazują na ten sam obiekt w pamięci). Ponieważ argumentem metody Equals() jest obiekt ogólnej klasy System.Object, pierwszym krokiem jest upewnienie się, czy przekazano obiekt odpowiedniej klasy. Należy również sprawdzić, czy przesłany parametr nie ma wartości null.

30 [email protected] Waldemar Bartyna Nadpisanie System.Object.Equals() 3 Zaimplementowana w ten sposób metoda Equals() będzie działać poprawnie. W przypadku klasy Person mieliśmy jednak tylko kilka pól prostych typów składających się na stan obiektu. W przypadku bardziej złożonych klas, częstym skrótem stosowanym w implementacji metody Equals() jest wykorzystywanie metody ToString() (ale tylko pod warunkiem, że została ona dobrze napisana –uwzględnia wartości wszystkich pól) 30

31 [email protected] Waldemar Bartyna Nadpisanie System.Object.GetHashCode() Kod hash to wartość liczbowa reprezentująca określony stan obiektu. Na przykład, dwa obiekty typu string zawierające napis „Hello”, mają ten sam kod hash. Jeżeli jeden z tych napisów będzie składał się tylko z małych liter („hello”), wartości kodu hash będą różne. Domyślnie, metoda GetHashCode() generuje kod na podstawie aktualnej lokalizacji danego obiektu w pamięci operacyjnej. Jeżeli tworzymy typ z myślą o umieszczaniu go w kolekcji Hashtable, musimy przesłonić zarówno metodę Equals(), jak i GetHashCode(), ponieważ obie te metody są wykorzystywane przez Hasztable w momencie pobierania obiektu. 31

32 [email protected] Waldemar Bartyna NadpisanieSystem.Object.GetHashCode() 2 Jest wiele sposobów tworzenia kodu hash. W większości przypadków można go wygenerować dla definiowanej klasy poprzez wykorzystanie metody GetHashCode() klasy System.String. Jednym ze sposobów jest zidentyfikowanie unikalnego pola i wywołanie dla nim metody GetHashCode(). Jeżeli takiego pola nie mamy, a nadpisaliśmy metodę ToString(), możemy to wykorzystać do wygenerowania kodu hash dla obiektów naszej klasy. 32

33 [email protected] Waldemar Bartyna Testowanie zmodyfikowanej klasy Person 33

34 [email protected] Waldemar Bartyna Wynik działania programu 34

35 [email protected] Waldemar Bartyna Statyczne składowe klasy System.Object Oprócz metod instancyjnych klasa System.Object definiuje również dwie metody statyczne  Equals(Object o1, Object o2) do porównywania stanów obiektów,  ReferenceEquals(Object o1, Object o2) do porównywania referencji. 35

36 [email protected] Waldemar Bartyna 36/24 Strukturalna obsługa wyjątków

37 [email protected] Waldemar Bartyna Rodzaje problemów Błędy programisty (ang. bugs): są rezultatem pomyłki twórcy aplikacji. Przykładem może być zezwolenie na przekroczenie indeksu w tablicy. Błędy użytkownika: mogą się pojawiać w pojedynczym uruchomieniu aplikacji, a nie w każdym (tak jak ma to miejsce w przypadku błędów programisty). Tradycyjnym przykładem jest wpisanie przez użytkownika danych niewłaściwego typu (napis zamiast liczby) lub podanie danych w niewłaściwym formacie. 37

38 [email protected] Waldemar Bartyna Rodzaje problemów (c. d.) Wyjątki: są z reguły postrzegane jako anomalie w czasie wykonania, które są trudne (albo których wręcz nie można) przewidzieć w czasie tworzenia aplikacji. Można do nich zaliczyć:  Próbę połączenia się z bazą danych, która już nie istnieje,  Otwieranie uszkodzonego pliku,  Próba nawiązania łączności z komputerem, aktualnie nie podłączonym do sieci,  Itp. 38

39 [email protected] Waldemar Bartyna Obsługa wyjątków w.NET Sam termin obsługa wyjątków może nam się kojarzyć jedynie z obsługą problemów w czasie wykonania. Na platformie.NET, silnik CLR często generuje odpowiedni wyjątek, który pozwala na identyfikację aktualnego problemu również w przypadku błędów programisty i użytkownika. W poprzednich architekturach (np. COM), z problemami radzono sobie poprzez stosowanie różnych technik, które często były specyficzne dla danego języka, a nawet projektu..NET wprowadza standardowy sposób obsługi błędów identyczny dla wszystkich języków platformy 39

40 [email protected] Waldemar Bartyna Zalety strukturalnej obsług wyjątków Jednakowe podejście do obsługi błędów, wspólne dla wszystkich języków Jednakowa składnia używana do wyrzucania i przechwytywania wyjątków we wszystkich językach W miejsce kodowania wyjątku w postaci mało mówiącej liczby, zostały wprowadzone wyjątki jako obiekty niosące ze sobą wiele przydatnych, czytelnych dla człowieka, informacji (jak również stan stosu, pomocnicze linki, i kilka innych) 40

41 [email protected] Waldemar Bartyna Elementy obsługi wyjątków Programowanie oparte na strukturalnej obsłudze wyjątków wiąże się z wykorzystaniem czterech elementów:  Klasy, która reprezentuje szczegółowe informacje o wyjątku  Składowej, która wyrzuca instancję odpowiedniej klasy wyjątku do wywołującego,  Bloku kodu po stronie wywołującego, w którym korzysta z mogącej wyrzucić wyjątek składowej,  Bloku kodu po stronie wywołującego, który przechwyci i obsłuży zgłoszony wyjątek. 41

42 [email protected] Waldemar Bartyna Słowa kluczowe Język C# posiada cztery słowa kluczowe związane z obsługą wyjątków:  try,  catch,  throw,  finally. Typem, który reprezentuje pojawiające się błędy jest klasa dziedzicząca po klasie System.Exception lub po jej pochodnych. 42

43 [email protected] Waldemar Bartyna Klasa bazowa System.Excepiton 43

44 [email protected] Waldemar Bartyna Cechy klasy System.Excepiton Wiele z właściwości jest zadeklarowana jako tylko do odczytu. Wynika to z tego, że typowym postępowaniem podczas tworzenia klasy pochodnej jest nadawanie tym właściwościom wartości domyślnych, które się później nie zmieniają. Klasa System.Exception implementuje dwa interfejsy:  ISerializable pozwala na utrwalanie lub przekazywanie danych obiektów na zewnątrz programu,  _Exception dzięki niemu wyjątki platformy.NET mogą być przetwarzane przez niezarządzany kod, takie jak aplikacje COM. 44

45 [email protected] Waldemar Bartyna Główne składowe klasy System.Exception Data – Właściwość ta pobiera kolekcję par klucz/wartość (reprezentowaną przez obiekt implementujący interfejs IDictionary), która dostarcza dodatkowe, zdefiniowane przez programistę, informacje o błędzie. Domyślnie jest ona pusta. HelpLink – Właściwość ta zwraca adres URL do pliku z pomocą lub do strony internetowej szczegółowo opisującej dany błąd. 45

46 [email protected] Waldemar Bartyna Główne składowe klasy System.Exception 2 InnerException – Ta właściwość tylko do odczytu może być używana do zdobycia informacji o wyjątkach, które wystąpiły podczas obsługi danego wyjątku. Wyjątki te są zapisywane poprzez przekazywanie ich jako argumentu konstruktora. Message – Ta właściwość tylko do odczytu zwraca tekstowy opis danego błędu. Jest ona ustawiana poprzez podanie jej jako argumentu konstruktora. Source – Właściwość ta zwraca nazwę pakietu, który dany wyjątek wyrzucił (zgłosił). 46

47 [email protected] Waldemar Bartyna Główne składowe klasy System.Exception 3 StackTrace – Ta właściwość tylko do odczytu zawiera łańcuch znaków identyfikujący sekwencję wywołań, która spowodowała dany wyjątek. Jest ona bardzo pomocna przy debugowaniu kodu lub zapisywaniu informacji o błędzie do dziennika. TargetSite – Ta właściwość tylko do odczytu zwraca typ MethodBase, który zawiera wiele szczegółów dotyczących metody, która dany wyjątek wyrzuciła (wywołanie metody ToString() wyświetli nazwę metody). 47

48 [email protected] Waldemar Bartyna Prosty przykład Klasa Radio 48

49 [email protected] Waldemar Bartyna Prosty przykład 2 49 Klasa Car

50 [email protected] Waldemar Bartyna Prosty przykład 3 50 Klasa Car (c. d.)

51 [email protected] Waldemar Bartyna Przykładowe wywołanie 51

52 [email protected] Waldemar Bartyna Wyrzucanie wyjątku 52

53 [email protected] Waldemar Bartyna Wyrzucanie wyjątku 2 Wyjątek jest zgłaszany wywołującemu daną metodę za pomocą słowa kluczowego throw. W konstruktorze obiektu (wyjątku) podawana jest wiadomość o rodzaju błędu (Message). Ważnymi kwestiami projektowymi jest ustalenie:  Jakie wydarzenie powinno powodować zgłoszenie wyjątku,?  Kiedy (w którym miejscu kodu) powinien on być wyrzucony?. Wyjątki powinny być wyrzucane w sytuacjach awaryjnych, z których dana metoda nie może automatycznie się „podnieść”, np. nieistniejący plik o wskazanej nazwie. 53

54 [email protected] Waldemar Bartyna Przechwytywanie wyjątku 54

55 [email protected] Waldemar Bartyna Przechwytywanie wyjątku 2 55

56 [email protected] Waldemar Bartyna Przechwytywanie wyjątku 3 W przypadku wywołania metody, która może wyrzucić wyjątek korzystamy z bloku try/catch. Z przechwyconego obiektu wyjątku możemy pobrać szczegółowe informacje o błędzie za pomocą odpowiednich właściwości. Blok try jest sekcją kodu, w którym może nastąpić wyrzucenie wyjątku. Jeżeli wyjątek zostanie wykryty, sterowanie zostaje przeniesione do odpowiedniego bloku catch. Z drugiej strony, jeżeli w bloku try nie wystąpił żaden wyjątek, blok catch zostaje w całości pominięty. Po obsłużeniu wyjątku sterowanie wraca do aplikacji do punktu zaraz po bloku catch. 56

57 [email protected] Waldemar Bartyna Konfigurowanie stanu wyjątka Obecnie, nasz obiekt klasy System.Exception wyrzucany przez metodę Accelerate() przekazuje nam tylko informacje poprzez właściwość Message (przekazywaną jako parametr konstruktora). Dodatkowe składowe klasy Exception mogą być użyte do dalszego, bardziej szczegółowego opisania samego błędu i powodu jego powstania. Te składowe to:  TargetSite,  StackTrace,  HelpLink,  Data. 57

58 [email protected] Waldemar Bartyna Właściwość TargetSite Właściwość System.Exception.TargetSite pozwala na ustalenie wielu szczegółów o metodzie, która wyrzuciła dany wyjątek. Wyświetlenie tej właściwości poprzez metodę ToString() pokaże nam zwracany typ, nazwę metody oraz typy jej parametrów. Wartość zwracana przez właściwość TargetSite jest typu System.Reflection.MethodBase. Zawiera on informacje nie tylko o samej metodzie, ale np. również o typie, w którym został zdefiniowany.  DeclaringTyp – mówi nam, o typie, w jakim dana metoda została zadeklarowana,  MemberType – mówi nam, składową jakiego typu jest dany element wyrzucający wyjątek. 58

59 [email protected] Waldemar Bartyna Właściwość TargetSite 2 59

60 [email protected] Waldemar Bartyna Właściwość TargetSite 3 60

61 [email protected] Waldemar Bartyna Właściwość StackTrace Właściwość System.Exception.StackTrace umożliwia zidentyfikowanie serii wywołań, które doprowadziły do wyrzucenia wyjątku Najniższy wpis odpowiada pierwszemu wywołaniu w sekwencji prowadzącej do powstania wyjątku Idąc w górę, możemy prześledzić kolejne wywołania, aż do metody, która dany wyjątek wyrzuciła. 61

62 [email protected] Waldemar Bartyna Właściwość HelpLink Właściwość TargetSite i StackTrace są pomocne dla programisty w debugowaniu kodu, ale mało mówią użytkownikowi aplikacji Właściwość Message może stanowić czytelny przekaż dla użytkownika końcowego aplikacji. Dodatkowo, właściwość HelperLink może wskazywać odpowiedni URL lub standardowy plik pomocy systemu Windows, który dokładnie opisuję błąd. Domyślnie, właściwość ta jest pusta. Jeżeli chcemy ją ustawić, musimy to zrobić jeszcze przed wyrzuceniem wyjątku. 62

63 [email protected] Waldemar Bartyna Właściwość HelpLink 2 63 Dodajemy odpowiednią linie w bloku catch Odpowiednia modyfikacja metody Accelerate()

64 [email protected] Waldemar Bartyna Właściwość Data Właściwość System.Exception.Data pozwala na dodanie do obiektu dodatkowych informacji o błędzie w postaci par klucz/wartość. Właściwość ta zwraca obiekt implementujący interfejs IDictionary zdefiniowany w przestrzeni nazw System.Collections. Przestrzeń tą musimy dodać po stronie wywołującego, jeżeli chcemy korzystać z typu DictionaryEntry (a chcemy). 64

65 [email protected] Waldemar Bartyna Właściwość Data 2 Odpowiednio modyfikujemy metodę Accelerate() i tworzenie wyjątku 65

66 [email protected] Waldemar Bartyna Właściwość Data 3 Odpowiednio modyfikujemy metodę main i przechwycenie wyjątku 66

67 [email protected] Waldemar Bartyna Właściwość Data 4 67

68 [email protected] Waldemar Bartyna Właściwość Data 5 Właściwość ta pozwala na przekazywanie wywołującemu większej ilości informacji bez konieczności tworzenia własnej klasy dziedziczącej po klasie Exception. Z drugiej strony tworzenie takich klas może być wygodniejsze, jeżeli wolimy przechwycić konkretny typ wyjątku (klasy), a nie „łapać” ogólną klasę i próbować znaleźć odpowiednie informacje we właściwości Data 68

69 [email protected] Waldemar Bartyna Wyjątki systemowe Biblioteka klas bazowych platformy.NET definiuje wiele klas (wyjątków) dziedziczących po klasie System.Exception, np.:  ArgumentOutOfRangeException  IndexOutOfRangeException,  StackOverflowException itp. Wyjątki wyrzucane przez platformę.NET nazywamy wyjątkami systemowymi. Wyjątki systemowe dziedziczą po klasie System.SystemException, która dopiero dziedziczy po klasie System. Exception Jak sprawdzić, czy klasa NullReferenceException jest wyjątkiem systemowym? 69

70 [email protected] Waldemar Bartyna Wyjątki aplikacji W odróżnieniu od wyjątków systemowych wyrzucanych przez klasy bazowej biblioteki lub silnik uruchomieniowy platformy.NET, wyjątki aplikacji definiowane są w ramach i wyrzucane na poziomie tworzonej aplikacji. Przy ich definiowaniu, dobrym zwyczajem jest dziedziczenie klasy System.ApplicationException, a nie bezpośrednio klasy System.Exception. Tak jak w przypadku wyjątków systemowych dziedziczenie po dodatkowej pośredniej klasie ma znaczenie prawie wyłącznie informacyjne (rozróżnienie wyjątków systemowych i aplikacyjnych). 70

71 [email protected] Waldemar Bartyna Tworzenie niestandardowych wyjątków Chociaż zawsze można wyrzucić wyjątek w postaci klasy Exception, a dodatkowe informacje przesłać za pomocą właściwości Data, w niektórych przypadkach może okazać się wygodniejsze zdefiniowanie właśnej klasy. Dobrą praktyką jest kończenie nazw klas będących wyjątkami słowem „Exception”. Regułą jest również nadawanie modyfikatora public tworzonym klasom (wyjątkom). Powodem jest to, że mogą one być wyrzucane na zewnątrz pakietu, a zatem wywołujący odpowiednią metodę musi mieć dostęp do klasy wyjątku. 71

72 [email protected] Waldemar Bartyna Tworzenie niestandardowych wyjątków 2 72 Definiujemy klasę CarIsDeadException

73 [email protected] Waldemar Bartyna Tworzenie niestandardowych wyjątków 3 73 Definiujemy klasę CarIsDeadException (c. d.)

74 [email protected] Waldemar Bartyna Tworzenie niestandardowych wyjątków 4 74 Odpowiednio modyfikujemy funkcję wyrzucającą wyjątek

75 [email protected] Waldemar Bartyna Tworzenie niestandardowych wyjątków 5 75 Zmieniamy nazwę klasy wyjątku, który spodziewamy się przechwycić

76 [email protected] Waldemar Bartyna Lepsze wyjątki Niestandardową klasę wyjątku definiujemy w przypadku, gdy błędy, które będą przez nie reprezentowane ściśle dotyczą dziedziny aplikacji, a nie ogólnych problemów. Zdefiniowana przez nas klasa dotyczy zachowania samochodu, a nie, np., przekroczenia indeksu w tablicy. W poprzedniej wersji klasy przeesłonilismy właściwość Message. Nie musimy tego robić. Wystarczy skorzystać z konstruktora klasy bazowej. Tym samym staje się niepotrzebne pole przechowujące wartość wiadomości. W większości przypadków, tworzenie klasy reprezentującej wyjątki związane z dziedziną aplikacji, sprowadzało się będzie do wprowadzenia klasy wyjątku o odpowiedniej, nowej nazwie. 76

77 [email protected] Waldemar Bartyna Lepsze wyjątki 2 77

78 [email protected] Waldemar Bartyna Wyjątki zgodne z dobrą praktyką.NET Jeżeli chcemy zdefiniować klasę wyjątku zgodną z dobrą praktyką.NET, należy:  Dziedziczyć po klasie Exception/ApplicationException,  Oznaczyć ją atrybutem [System.Serializable],  Zdefiniować konstruktor domyślny,  Zdefiniować konstruktor ustawiający właściwość Message,  Zdefiniować konstruktor obsługujący wyjątki wewnętrzne,  Zdefiniować konstruktor obsługujący serializację danego typu. 78

79 [email protected] Waldemar Bartyna Wyjątki zgodne z dobrą praktyką.NET 2 79 Wersja uwzględniająca wszystkie wymagane elementy

80 [email protected] Waldemar Bartyna Korzystajmy z udogodnień środowiska! Skoro znane są zasady tworzenia wyjątków zgodnych z dobrą praktykę, to powinny istnieć narzędzia do wspomagania ich tworzenia. I oczywiście istnieją! Z menu kontekstowego wybieramy Insert snippet … Następnie wybieramy Visual C# Z listy dostępnych „gotowców” wybieramy exception. Nadajemy nazwę klasie wyjątku, ewentualnie zmieniamy klasę bazową. Uzupełniamy definicję klasy o dodatkowe dane i właściwości. Voilà ! 80

81 [email protected] Waldemar Bartyna Przetwarzanie wielu wyjątków Zmodyfikujmy odpowiednio metodę Accelaerate() dodając wyrzucanie jeszcze jednego wyjątku. 81

82 [email protected] Waldemar Bartyna Przetwarzanie wielu wyjątków 2 Teraz będziemy przechwytywać dwa typy wyjątków 82

83 [email protected] Waldemar Bartyna Przetwarzanie wielu wyjątków 3 83

84 [email protected] Waldemar Bartyna Przetwarzanie wielu wyjątków 4 Sposób przechwycenie wielu wyjątków pokazany na poprzednim slajdzie spowoduje błąd w czasie kompilacji. Powodem jest to, że pierwszy w kolejności blok catch przechwytuje najbardziej ogólny wyjątek, czyniąc kolejne bloki nieosiągalnymi. Bloki catch należy definiować w kolejności od najbardziej specjalizowanych do najbardziej ogólnych. Kolejny slajd pokazuje prawidłowe uszeregowanie bloków catch. 84

85 [email protected] Waldemar Bartyna Przetwarzanie wielu wyjątków 5 85

86 [email protected] Waldemar Bartyna Ogólny blok catch Nie pozwala na uzyskanie danych o błędzie, tylko ogólnie o fakcie wystąpienia błędu. Przydatne, jeżeli wprowadzamy obsługę błędów na bardzo ogólnym poziomie. 86

87 [email protected] Waldemar Bartyna Przerzucanie wyjątku Przerzucanie obsługi wyjątku do wyższego poziomu aplikacji ma sens, jeżeli wiemy, że będzie on w stanie poprawnie go obsłużyć, a sami tego nie możemy zrobić. Użycie słowa throw bez parametrów powoduje przerzucenie wyjątku w nienaruszonej postaci. 87

88 [email protected] Waldemar Bartyna Wyjątki wewnętrzne W przypadku wystąpienia wyjątku podczas obsługi wyjątku (czyli w bloku catch), powinniśmy udokumentować jego wystąpienia. Czynimy to poprzez utworzenie i zgłoszenie oryginalnego wyjątku, przekazując jako drugi parametr konstruktora (czyli ustawiając właściwość InnerException) obiekt wewnętrznego wyjątku. Podejście takie ma sens, jeżeli odbiorca będzie potrafił obsłużyć taki wyjątek 88

89 [email protected] Waldemar Bartyna Blok finally Blokowi try/catch może również towarzyszyć opcjonalny blok finally. Blok finally jest wywoływany zawsze, nie zależnie czy wystąpił wyjątek czy nie. Stanowi najwłaściwsze miejsce do porządnego „posprzątania”:  Pozbycie się niepotrzebnych obiektów,  Zamknięcie plików,  Rozłączenie się z bazą danych. 89

90 [email protected] Waldemar Bartyna Blok finally 2 90

91 [email protected] Waldemar Bartyna Kilka uwag Platforma.NET (w przeciwieństwie do Javy) nie obsługuje sprawdzanych wyjątków, co oznacza, że obsługa wyjątków jest całkowicie opcjonalna (kompilator jej nie wymusza). Aby sprawdzić, jakie wyjątki są wyrzucane przez daną metodę, można sięgnąć do dokumentacji platformy.NET lub skorzystać z opisu metody pojawiającego się po najechaniu kursorem myszy na nazwę tej metody. Nie obsłużone wyjątki wyświetlane są przy pomocy odpowiedniego okna dialogowego w czasie wykonania programu. Możemy się w nim zapoznać ze wszystkimi omówionymi składowymi wyjątków. 91

92 [email protected] Waldemar Bartyna Pytania egzaminacyjne (Zestaw05) 23.Czym charakteryzuje się klasa System.Object? 24.Na czym polega obsługa wyjątków? 25.Jakie są bloki i słowa kluczowe związane z obsługą wyjątków? 26.Jak realizujemy przechwytywanie wielu wyjątków? 92

93 [email protected] Waldemar Bartyna 93 Dziękuję za uwagę