Obsługa wyjątków
Typ pusty
Typy wartościowe mają wersję typu umożliwiającą przypisanie wartości null
.
Deklaracja:
typ? nazwa = null;
Przykład:
int? a = null; int? b = 42; double? x = null; bool? czy_prawda = null; //int k = null; // ta deklaracja nie jest dozwolona
Operator ??
Operator ??
ułatwia obsługę sytuacji, gdy zmienna posiada wartość null
. W takiej sytuacji ??
zwraca wartość podaną po prawej stronie.
int? x = null; int y = x ?? 42; string linia = Console.ReadLine() ?? "";
Równoważnie
if (x == null) y = 42;
Wyjątki
Źródło: Learn Coding from Experts
- Wyjątki - odpowiedź na nieoczekiwane zdarzenia w trakcie wykonywania programu, np. dzielenie przez zero, niepoprawne rzutowanie.
- Wystąpienie wyjątku przerywa działanie programu
- Rzucony wyjątek możemy „złapać” zabezpieczając wrażliwy fragment kodu instrukcją
try
catch
- Informacje o wyjątkach rzucanych z metody opisane są w dokumentacji
Przykład: Convert.ToInt32() - Rzucanie wyjątków, instrukcja
throw
- Predefiniowane wyjątki
System.Exception
Łapanie wyjątków
Składnia
try { // blok kodu, w którym spodziewamy się wyjątku } catch(TypWyjątku ex) { // obsługa wyjątku konkretnego typu }
Przykład
string napis = Console.ReadLine(); int wynik = 0; try { wynik = Convert.ToInt32(napis); Console.WriteLine($"Zamieniam '{napis}' na wartość typu int {wynik}."); } catch (FormatException) { Console.WriteLine($"'{napis}' nie jest liczbą całkowitą."); }
Przykład
string napis = Console.ReadLine(); int wynik = 0; try { wynik = Convert.ToInt32(napis); Console.WriteLine($"Zamieniam napis '{napis}' na wartość typu int {wynik}."); } catch (OverflowException) { Console.WriteLine($"{napis} jest poza zakresem typu int"); } catch (FormatException) { Console.WriteLine($"Napis '{napis}' nie jest liczbą całkowitą."); }
Hierarchia wyjątków
- Wyjątki zorganizowane są w hierarchię
- Każdy wyjątek jest typu
System.Exception
(najogólniejszy)
Przykład: Exception
try { int wynik = Convert.ToInt32("Ala ma kota"); } catch(Exception e) { Console.WriteLine($"Złapałem wyjątek {e}"); }
Try catch finally
Sekcja finally
jest uruchamiana na końcu sekcji try/catch
, wykorzystywana jest do zwalniania zasobów zarezerwowanych w instrukcji try
(np. zamknięcie pliku)
try { // blok kodu, w którym spodziewamy się wyjątku } catch(TypWyjątku ex) { // obsługa wyjątku konkretnego typu } finally { // Kod uruchamiany ZAWSZE, niezależnie od tego, czy wystąpił wyjątek }
Typowe wyjątki
Typ | Opis |
---|---|
ArithmeticException | błędna operacja arytmetyczna (dzielenie przez 0, nadmiar) |
DivideByZeroException | dzielenie przez zero |
OverflowException | nadmiar, przekroczenie zakresu typu |
ArrayTypeMismatchException | niepoprawny typ elementu tablicy |
IndexOutOfRangeException | indeks poza zakresem tablicy |
InvalidCastException | niepoprawne rzutowania |
NullReferenceException | odwołanie do wartości null zamiast do obiektu |
OutOfMemoryException | brak pamięci (niepowodzenie operacji new ) |
ArgumentException | niepoprawny argument metody |
StackOverflowException | przepełnienie stosu (np. nieskończona rekurencja) |
IO.IOException | błąd obsługi wejścia/wyjścia (pliki) |
IO.FileNotFoundException | próba dostępu do nieistniejącego pliku |
Rzucanie wyjątków
W sytuacjach wyjątkowych rzucamy wyjątek odpowiedniego typu
throw new Exception("Komunikat wyjątku");
if(x == 0) throw new DivideByZeroException(); int y=1 / x;
TryParse
Niektóre metody komunikują wystąpienie błedu zwracając odpowiednia wartość
int x; string s = Console.ReadLine(); if (int.TryParse(s, out int wartość)) { x = wartość; } else { Console.WriteLine("Błąd formatowania"); }
Ćwiczenie
Napisz metodę wyznaczającą pierwiastek kwadratowy $\sqrt{a}$ liczby rzeczywistej za pomocą algorytmu Herona.
W przypadku niepoprawnego argumentu $a<0$ metoda rzuca wyjątek ArgumentException
z odpowiednim komunikatem.
Napisz program, który wczyta z konsoli liczbę i wyznaczy jej pierwiastek kwadratowy. Obsłuż wszystkie sytuacje wyjątkowe (niepoprawny format liczby, zły argument metody pierwiastkującej).
Przybliżenie pierwiastka liczby $a$ wyznaczamy wzorem iteracyjnym
$$x_{i+1} =\frac{1}{2} \left( x_i + \frac{a}{x_i}\right)$$
Algorytm:
- ustaw wartości początkowe $x_0=1, i=0, \epsilon=0.0000001$
- oblicz $x_{i+1}$
- jeśli $|x_{i+1} - x_i | < \epsilon$ to zwróć pierwiastek równy $x_{i+1}$
- zwiększ $i=i+1$ i wróć do pkt. 2