Udostępnij za pośrednictwem


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ą typu string tylko do odczytu, która zawiera czytelny dla człowieka opis przyczyny wyjątku.
  • InnerException jest właściwością tylko do odczytu typu Exception. 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ącym InnerExceptionelement . W przeciwnym razie jego wartość to null, 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 obiektu System.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ć.