Wyjątki to problemy, które pojawiają się w trakcie wykonywnia programu. W języku C# wyjątki to odpowiedź na nieoczekiwane zdarzenia do których dochodzi w trakcie wykonywania programu. Możemy do nich zaliczyć próbę dzielenia przez 0.

Wyjątki pozwalają na przeniesienie kontroli z jednej części programu do innej. W C# wyjątki są obsługiwane za pomocą czterech słów kluczowych: try, catch, finally oraz throw.

  • try - określa blok kodu dla którego obsługa wyjątków jest aktywna. Składa się z jednej lub większej ilości bloków catch;
  • catch - program wyłapuje wyjątki w miejscu w którym chcesz te wyjątki obsłużyć. Słowo kluczowe catch wskazuje miejsce wyłapania wyjątku;
  • finally - blok ten jest używany do wywoływania pewnego bloku poleceń niezależnie od tego czy wyjątek został wyrzucony czy nie. Dla przykładu, jeżeli został otwarty plik musi on zostać zamknięty nie ważne czy błąd został rzucony czy nie;
  • throw - program rzuca wyjątek kiedy pojawi się problem. Odbywa się to za pomocą słowa kluczowego throw.

Składnia

Zakładając, że blok kodu rzuci wyjątek, metoda wyłapie ten wyjątek za pomocą kombinacji słow try i catch. Blok ten jest umieszczony wokół kodu, który może wygenerować wyjątek. Kod wewnątrz tego bloku nazywany jest kodem chronionym a składnia wygląda następująco:
try
{
   // blok kodu, który może rzucić wyjątkiem
}
catch(NazwaWyjatku e1 )
{
   // obsługa wyjątku
}
catch(NazwaWyjatku e2 )
{
   // obsługa wyjątku
}
catch(NazwaWyjatku eN )
{
   // obsługa wyjątku
}
finally
{
   // blok, który zostanie wykonany zawsze
}

Tak jak w powyższym przykładzie, można wyłapać wiele różnych rodzajów wyjątków i w zależności od rodzaju błędu dokonać jego obsługi.

Klasa Exception

W języku C# wyjątki reprezentowane są przez klasy. Klasy wyjątków są głównie pośrednio lub bezpośrednio dziedziczące z klasy System.Exception. Niektóre z klas wyjątków dziedziczące z klasy System.Exception pochodzą z klasy System.ApplicationException oraz klasy System.SystemException.

Klasa System.ApplicationException obsługuje wyjątki generowane przez aplikację. Wszystkie błędy zdefinowane przez programistę powinny pochodzić z tej klasy.

Klasa System.SystemException jest klasą bazową dla wszystkich predefiniowanych wyjątków systemowych.

Poniższa tabela zawiera kilka predefiniowanych wyjątków pochodzących z klasy System.SystemException:
Klasa wyjątku Opis
System.IO.IOException obsługa wyjątków związanych z odczytawaniem/zapisywaniem plików
System.IndexOutOfRangeException obsługa wyjątków związanych z tablicami, a ściślej z wyjściem indeksu poza dopuszczalny zakres
System.ArrayTypeMismatchException obsługa wyjątków związanych z niezgodnością typu z typem danej tablicy
System.NullReferenceException obsługa wyjatków związanych z typem pustym
System.DivideByZeroException obsługa wyjątków związanych z dzieleniem przez zero
System.InvalidCastException obsługa wyjatków związanych z niepoprawnym rzutowaniem
System.OutOfMemoryException obsługa wyjątków związanych z niewystarczającą ilością pozostałej pamięci
System.StackOverflowException obsługa wyjątków związanych z przepełniem stosu
Obsługa wyjątków

C# oferuje rozwiązania pozwalające na obsługę wyjątków. Korzystanie z tych bloków to podstawa zabezpiecznia naszych programów przed nieoczekiwanym zamknięciem.

Poniżej przykład obsługi wyjątku powstającego przy próbie dzielenia przez 0:
using System;
namespace ObslugaWyjatkow
{
    class Program
    {
        static void Main(string[] args)
        {
            DzieleniePrzezZero dpz = new DzieleniePrzezZero(8, 0);
            Console.ReadKey();
        }
    }
    class DzieleniePrzezZero
    {
        int result = 0;
        public DzieleniePrzezZero(int a, int b)
        {
            try
            {
                result = a / b;
            }
            catch (DivideByZeroException ex)
            {
                Console.WriteLine("Zgłoszono wyjątek: {0}", ex);
            }
        }
    }
}

Wyjątki definiowane przez użytkownika

Możesz również sam zdefiniować wyjątek. Wyjątki zdefiniowane przez użytkownika powinny pochodzić z klasy System.ApplicationException.
Przykład:
using System;
namespace ObslugaWyjatkowWlasne
{
    class Program
    {
        static void Main(string[] args)
        {
            Wiek w = new Wiek();
            try
            {
                w.SprawdzWiek(-34);
            }
            catch (MojWlasnyWyjatek ex)
            {
                Console.WriteLine("MojWlasnyWyjatek: {0}", ex.Message);
            }
            Console.ReadKey();
            // Wynik działania programu
            //MojWlasnyWyjatek: Wiek nie moze byc mniejszy niz 0
        }
    }
    class MojWlasnyWyjatek : ApplicationException
    {
        // Przekazujemy do klasy bazowej parametr naszego konstruktora
        public MojWlasnyWyjatek(string text): base(text)
        {
        }
    }
    class Wiek
    {
        int wiek = 0;
        public void SprawdzWiek(int a)
        {
            wiek = a;
            // Krótkie wyjaśnienie - słowo kluczowe throw
            // Używamy do rzucania wyjątków w określonym miejscu w kodzie
            // W poniższym przykładzie rzucamy nasz własny wyjątek wraz z
            // tekstem, którą chcemy wyświetlić
            if (wiek < 0)
                throw (new MojWlasnyWyjatek("Wiek nie może być mniejszy niż 0"));
            else
                Console.WriteLine("Poprawny wiek: {0}", wiek);
        }
    }
}