Глиф Учебники

Как обработать ошибку — try, catch и finally

Справочник · C# · 2 минуты чтения

C#
Console.Write("Делимое: ");
string a = Console.ReadLine() ?? "";
Console.Write("Делитель: ");
string b = Console.ReadLine() ?? "";

try
{
    int x = int.Parse(a);
    int y = int.Parse(b);
    Console.WriteLine($"Частное: {x / y}");
}
catch (FormatException)
{
    Console.WriteLine("Нужно ввести целые числа");
}
catch (DivideByZeroException)
{
    Console.WriteLine("На ноль делить нельзя");
}
finally
{
    Console.WriteLine("Готово");
}
Текст
Делимое: 10
Делитель: 0
На ноль делить нельзя
Готово

Исключение — сигнал об ошибке во время работы программы: строку не удалось перевести в число, файла нет, делитель равен нулю. Если его не поймать, программа останавливается с сообщением вроде Unhandled exception. System.DivideByZeroException: Attempted to divide by zero.

Как только в try случилась ошибка, остальные его строки пропускаются, и выполнение переходит в подходящий catch.

Текст ошибки и общий catch

У каждого исключения есть свойство Message — описание ошибки. А catch (Exception ex) ловит любое исключение:

C#
try
{
    int[] a = new int[3];
    a[5] = 1;
}
catch (Exception ex)
{
    Console.WriteLine($"Ошибка: {ex.Message}");
}
Вывод
Ошибка: Index was outside the bounds of the array.

Общий catch (Exception) ставят последним: блоки проверяются сверху вниз, и после общего до частных дело не дойдёт — компилятор так и скажет (ошибка CS0160).

Своё исключение: throw

Метод может сам сообщить об ошибке через throw:

C#
try
{
    CheckAge(25);
    CheckAge(-5);
}
catch (ArgumentException ex)
{
    Console.WriteLine($"Ошибка: {ex.Message}");
}

static void CheckAge(int age)
{
    if (age < 0)
    {
        throw new ArgumentException("возраст не может быть отрицательным");
    }
    Console.WriteLine($"Возраст: {age}");
}
Вывод
Возраст: 25
Ошибка: возраст не может быть отрицательным

Частые готовые типы: ArgumentException (неверный аргумент), ArgumentOutOfRangeException (вне допустимого диапазона), InvalidOperationException (сейчас так делать нельзя). Все исключения наследуют класс Exception, поэтому catch (Exception) ловит их все.

Подводные камни