21 Wyjątki
21.1 Ogólne
Wyjątki w języku C# zapewniają ustrukturyzowany, jednolity i bezpieczny dla typu sposób obsługi zarówno warunków błędów na poziomie systemu, jak i na poziomie aplikacji.
21.2 Przyczyny wyjątków
Wyjątki można zgłaszać na dwa różne sposoby.
- Instrukcja
throw
(§13.10.6) zgłasza wyjątek natychmiast i bezwarunkowo. Kontrolka nigdy nie osiąga instrukcji bezpośrednio po .throw
- Niektóre wyjątkowe warunki, które występują podczas przetwarzania instrukcji i wyrażeń języka C#, powodują zgłoszenie wyjątku w pewnych okolicznościach, gdy nie można ukończyć operacji normalnie. Zobacz §21.5 , aby uzyskać listę różnych wyjątków, które można zgłosić w ten sposób.
Przykład: Operacja dzielenia liczby całkowitej (§12.10.3) zgłasza wartość
System.DivideByZeroException
, jeśli mianownik ma wartość zero. przykład końcowy
21.3 Klasa System.Exception
Klasa System.Exception
jest podstawowym typem wszystkich wyjątków. Ta klasa ma kilka godnych uwagi właściwości, które współużytkuje wszystkie wyjątki:
Message
jest właściwością typustring
tylko do odczytu, która zawiera czytelny dla człowieka opis przyczyny wyjątku.InnerException
jest właściwością tylko do odczytu typuException
. Jeśli jego wartość nie jestnull
taka, odwołuje się do wyjątku, który spowodował bieżący wyjątek. (Oznacza to, że bieżący wyjątek został zgłoszony w bloku catch obsługującymInnerException
element . W przeciwnym razie jego wartość tonull
, co oznacza, że ten wyjątek nie był spowodowany przez inny wyjątek. Liczba obiektów wyjątków w łańcuchu w ten sposób może być dowolna.
Wartość tych właściwości można określić w wywołaniach konstruktora wystąpienia dla elementu System.Exception
.
21.4 Sposób obsługi wyjątków
Wyjątki są obsługiwane przez instrukcję try
(§13.11).
Gdy zgłaszany jest wyjątek (§21.2), system wyszukuje najbliższą klauzulę catch, która może obsłużyć wyjątek określony przez typ czasu wykonywania wyjątku. Po pierwsze, bieżąca metoda jest wyszukiwana pod kątem instrukcji leksykalnie otaczającej try
, a skojarzone catch
klauzule instrukcji try
są brane pod uwagę w kolejności. Jeśli to się nie powiedzie, metoda, która nazwała bieżącą metodę, jest wyszukiwana leksykalnie otaczającej try
instrukcję, która otacza punkt wywołania bieżącej metody. To wyszukiwanie będzie kontynuowane do momentu catch
znalezienia klauzuli , która może obsłużyć bieżący wyjątek, nazewając klasę wyjątku, która jest tej samej klasy lub klasy bazowej, typu czasu wykonywania zgłaszanego wyjątku. Klauzula catch
, która nie nazywa klasy wyjątku, może obsłużyć żaden wyjątek.
Po znalezieniu zgodnej catch
klauzuli system przygotowuje się do przeniesienia kontroli do pierwszej instrukcji klauzuli catch
. Przed rozpoczęciem wykonywania klauzuli catch
system najpierw wykonuje w kolejności wszystkie finally
klauzule skojarzone z instrukcjami try
bardziej zagnieżdżone niż ta, która przechwyciła wyjątek.
Jeśli nie znaleziono zgodnej catch
klauzuli:
- Jeśli wyszukiwanie klauzuli dopasowania
catch
osiągnie statyczny konstruktor (§15.12) lub inicjator pola statycznego,System.TypeInitializationException
zostanie zgłoszony w momencie wyzwolenia wywołania konstruktora statycznego. Wewnętrzny wyjątek obiektuSystem.TypeInitializationException
zawiera wyjątek, który został pierwotnie zgłoszony. - W przeciwnym razie, jeśli podczas wykonywania finalizatora wystąpi wyjątek i ten wyjątek nie zostanie przechwycony, zachowanie jest nieokreślone.
- W przeciwnym razie jeśli wyszukiwanie pasujących
catch
klauzul osiągnie kod, który początkowo uruchomił wątek, wykonanie wątku zostanie zakończone. Wpływ takiego zakończenia jest definiowany przez implementację.
21.5 Typowe klasy wyjątków
Następujące wyjątki są zgłaszane przez niektóre operacje języka C#.
Typ wyjątku | Opis |
---|---|
System.ArithmeticException |
Klasa bazowa dla wyjątków występujących podczas operacji arytmetycznych, takich jak System.DivideByZeroException i System.OverflowException . |
System.ArrayTypeMismatchException |
Zgłaszany, gdy magazyn do tablicy kończy się niepowodzeniem, ponieważ typ przechowywanego elementu jest niezgodny z typem tablicy. |
System.DivideByZeroException |
Zgłaszany podczas próby podzielenia wartości całkowitej przez zero. |
System.IndexOutOfRangeException |
Zgłaszany podczas próby indeksowania tablicy za pośrednictwem indeksu, który jest mniejszy niż zero lub poza granicami tablicy. |
System.InvalidCastException |
Zgłaszany, gdy jawna konwersja z typu podstawowego lub interfejsu na typ pochodny kończy się niepowodzeniem w czasie wykonywania. |
System.NullReferenceException |
Zgłaszany, gdy null odwołanie jest używane w sposób, który powoduje, że odwołany obiekt jest wymagany. |
System.OutOfMemoryException |
Zgłaszany podczas próby przydzielenia pamięci (za pośrednictwem new ) kończy się niepowodzeniem. |
System.OverflowException |
Zgłaszany, gdy operacja arytmetyczna w checked kontekście przepełnia się. |
System.StackOverflowException |
Zgłaszany, gdy stos wykonywania jest wyczerpany przez zbyt wiele oczekujących wywołań; zazwyczaj wskazuje na bardzo głęboką lub niezwiązaną rekursję. |
System.TypeInitializationException |
Zgłaszany, gdy konstruktor statyczny lub inicjator pola statycznego zgłasza wyjątek, a żadna klauzula nie catch istnieje, aby go przechwycić. |
ECMA C# draft specification