Рубріки: Теория

Что такое исключения в C# и как работать с блоками try, catch и finally

Александр Тартачный

Обработка исключений — способ предотвратить ошибки в исполнении программы. Чтобы обработать Exception (исключение) в языке C# используют операторы try, catch и finally.

Содержание статьи:

1. Вступление

2. Try, catch, finally и throw: сновные команды в С#

3. Exception: типы исключений в C#

4. Пример c try и catch в C# (example)

5. Алгоритм выполнения операторов try, catch и finally в C#

6. Ошибки в приложениях с визуальным интерфейсом

7. Генерирование исключительных ситуаций

8. Фильтры и условные конструкции

9. В заключение

Вступление

Часто во время выполнения программ возникают ошибки, которые не связаны с плохим написанием кода. Например, программе нужно найти пользователя, который отсутствует в базе данных, или подключенный файл оказался поврежденным.

Некоторые из ошибок происходят случайным образом и их невозможно предвидеть. Их называют исключениями.

Try, catch, finally и throw: основные команды в С#

Исключения позволяют программе передавать управление между частями кода, «пропуская» ошибку выполнения программы. Для этого в C# существуют команды try, catch, finally, а также throw:

  • Блок try применяют для инкапсуляции. В него помещают так называемый «ненадежный» код, который может выдать ошибку. Там могут содержаться вызовы методов, обращения к интерфейсам, операторы цикла. В случае, если некая строка из этого блока выдает исключение, то он обрабатывается в блоке catch.
  • Когда происходит исключение, запускается блок catch. Здесь исключение можно обработать. Варианты обработки зависят от задач разработчиков и типа ошибки. Например, записать ошибку в лог, завершить работу скрипта или прописать выдачу конкретного сообщения. В случае, если блок catch пустой, программа пропустит исключение.
  • Задача блока finallyвыполнить определенный код вне зависимости от того, сработало исключение или нет. Это может быть, к примеру, освобождение объекта из памяти. Иногда блок finally не обязателен и опускается. Так происходит, когда обработка исключения предусматривает, что программа дальше будет выполняться.
  • В языке C# существует несколько стандартных типов исключений, но есть возможность создавать их самостоятельно. Для этого используют оператор throw.

Exception: типы исключений в C#

При работе с ошибками в C# используют тип исключения Exception. Он базовый и включает все исключения. У него есть несколько свойств, с помощью которых можно получить сведения об исключении. Например, определить расположение, причину исключения, тип.

В таблице ниже перечислим несколько свойств.

Свойство Функция
InnerException Выдача экземпляра класса, вызвавшего исключение
Source Указание на имя объекта, который вызвал исключение
Message Текст ошибки
HelpLink Ссылка на файл справки, связанный с исключениями.

Если нужно обработать только определенные ошибки, используют конкретный тип исключений.

Давайте рассмотрим несколько наиболее популярных.

Тип исключения Значение
ArgumenOutOfRangeException Значение аргумента не соответствует допустимому диапазону
IndexOutOfRangeException Выход за диапазон массива или допустимых значений
StackOverflowException Переполнение стека
OutOfMemoryException Недостаточно памяти для выполнения программы
NullReferenceException Обращение к неопределенному объекту

Пример c try и catch в C# (example)

Вот пример обработки исключения типа IndexOutOfRangeException с операторами try и catch в C#:

// Exception handling of above code
// using try catch blocks
 
using System;
 
class Program : System.Exception {
    static void Main(string[] args)
    {
        // Declare an array of max index 4
        int[] arr = { 1, 2, 3, 4, 5 };
 
        // Display values of array elements
        for (int i = 0; i < arr.Length; i++) {
            Console.WriteLine(arr[i]);
        }
 
        try {
 
            // Try to access invalid index of array
            Console.WriteLine(arr[7]);
            // An exception is thrown upon executing
            // the above line
        }
        catch (IndexOutOfRangeException e) {
 
            // The Message property of the object
            // of type IndexOutOfRangeException
            // is used to display the type of exception
            // that has occurred to the user.
            Console.WriteLine("An Exception has occurred : {0}", e.Message);
        }
    } 

Обработку разных типов можно разграничить. Для этого каждый тип прописывают в отдельном блоке catch. Здесь важно помнить о приоритетности выполнения, так как предложения catch будут срабатывать в порядке написания.

Если менее конкретные исключения будут записаны перед более конкретными, то компилятор может выдать ошибку из-за невозможности достигнуть следующего блока.

Пример многоразового использования блока catch в C#:

// C# Program to show use of
// multiple try catch blocks
using System;
 
class Program {
 
    static void Main(string[] args)
    {
        int[] arr = {19, 0, 75, 52};
 
        try {
 
            // Try to generate an exception
            for (int i = 0; i < arr.Length; i++) {
                Console.WriteLine(arr[i] / arr[i + 1]);
            }
        }
 
        // Catch block for invalid array access
        catch (IndexOutOfRangeException e) {
 
            Console.WriteLine("An Exception has occurred : {0}", e.Message);
        }
 
        // Catch block for attempt to divide by zero
        catch (DivideByZeroException e) {
 
            Console.WriteLine("An Exception has occurred : {0}", e.Message);
        }
 
        // Catch block for value being out of range
        catch (ArgumentOutOfRangeException e) {
 
            Console.WriteLine("An Exception has occurred : {0}", e.Message);
        }
 
        // Finally block
        // Will execute irrespective of the above catch blocks
        finally {
            for (int i = 0; i < arr.Length; i++) {
                Console.Write(" {0}", arr[i]);
            }
        }
    }
}

Алгоритм выполнения операторов try, catch и finally в C#

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

Когда в блоке try произошла ошибка, то выполнение программы приостанавливается, а общеязыковая исполняющая среда (CLR) производит поиск блока catch. Если блок найден, то после его выполнения идет блок finally. В другом случае программа аварийно завершит работу.

Например, в случае деления на 0, возникает исключение System.DivideByZeroException. Чтобы не возникало таких ошибок, в блоке catch прописываем инструкцию, как указано в примере кода. Алгоритм не будет делить на 0 и выводить результаты, а программа аварийно завершается.

Теперь давайте посмотрим поближе на пример использования try и catch в C#:

//C#: Exception Handling
using System;
class MyClient
{
    public static void Main()
    {
        int x = 0;
        int div = 0;
        try
        {
            div = 100 / x;
            Console.WriteLine("This linein not executed");
        }
        catch (DivideByZeroException)
        {
            Console.WriteLine("Exception occured");
        }
        Console.WriteLine($"Result is {div}");
    }
} 

Ошибки в приложениях с визуальным интерфейсом

Все вышеуказанные правила работают в консольных приложениях. Если в программы есть интерфейс, то при возникновении ошибки увидим соответствующее окно:

Пример ошибки в Microsoft Visual Studio

В таком случае разработчик может попробовать продолжить выполнение программы, прервать его или изменить настройки и обработать исключение.

Генерирование исключительных ситуаций

В некоторых очевидных ситуациях (таких, как деление на 0) C# самостоятельно сгенерирует исключение. Чтобы создать персональное исключение, применяют оператор throw. Использование собственного класса исключений ограничивается лишь фантазией разработчика.

Например, у нас есть платформа для разработки ASP.NET. Платформа должна разрешать пользователю иметь только один сеанс в системе и выдавать сообщение об ошибке, если он вошел с другого окна браузера. 

Пример решения: 

namespace ExceptionHandlingDemo
{
    //Creating our own Exception Class by inheriting Exception class
    public class OddNumberException : Exception
    {
        //Overriding the Message property
        public override string Message
        {
            get
            {
                return "divisor cannot be odd number";
            }
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            int x, y, z;
            Console.WriteLine("ENTER TWO INTEGER NUMBERS:");
            x = int.Parse(Console.ReadLine());
            y = int.Parse(Console.ReadLine());
            try
            {
                if (y % 2 > 0)
                {
                    //OddNumberException ONE = new OddNumberException();
                    //throw ONE;
                    throw new OddNumberException();
                }
                z = x / y;
                Console.WriteLine(z);
            }
            catch (OddNumberException one)
            {
                Console.WriteLine(one.Message);
            }

            Console.WriteLine("End of the program");
            Console.ReadKey();
        }
    }
}

Фильтры и условные конструкции

Применять блоки try, catch и finnaly в C# требует больших производительных ресурсов, и это не всегда необходимо. Иногда лучше применить условные конструкции. Например, программа запрашивает ввод числа, а вместо этого пользователь использовал число прописью (строку). В таком случае лучше использовать преобразование типов.

Метод Int32.TryParse выдаст значение true, если тип возможно преобразовать. Таким образом для этого типа ошибок необязательно применять try / catch.

Блок catch тоже можно реализовать по-разному. Наиболее простой способ в C# — обрабатывать любое исключение (тип Exceptions). Но разработчикам все же советуют перехватывать только те исключения, которые они смогут восстановить. Также в C# есть возможность настроить обработку исключений только при конкретных условиях. После выражения catch используют оператор when, где указывают условие. Обработка будет происходить только в случае, если значение в условии истинное.

В заключение

Реализовать обработку исключений в C# можно разными способами. Некоторые распространенные ошибки возможно уловить с помощью стандартных типов исключений. Нужно понимать свойства ошибок, чтобы учиться с ними работать. Также важно учитывать последовательность исключений. 

Помните, что в случае, если C# не имеет функционала для предотвращения такого исключения, его можно создать самостоятельно.  

Видео: обработка исключений в языке программирования C#

Останні статті

Обучение Power BI – какие онлайн курсы аналитики выбрать

Сегодня мы поговорим о том, как выбрать лучшие курсы Power BI в Украине, особенно для…

13.01.2024

Work.ua назвал самые конкурентные вакансии в IТ за 2023 год

В 2023 году во всех крупнейших регионах конкуренция за вакансию выросла на 5–12%. Не исключением…

08.12.2023

Украинская IT-рекрутерка создала бесплатный трекер поиска работы

Unicorn Hunter/Talent Manager Лина Калиш создала бесплатный трекер поиска работы в Notion, систематизирующий все этапы…

07.12.2023

Mate academy отправит работников в 10-дневный оплачиваемый отпуск

Edtech-стартап Mate academy принял решение отправить своих работников в десятидневный отпуск – с 25 декабря…

07.12.2023

Переписки, фото, история браузера: киевский программист зарабатывал на шпионаже

Служба безопасности Украины задержала в Киеве 46-летнего программиста, который за деньги устанавливал шпионские программы и…

07.12.2023

Как вырасти до сеньйора? Девелопер создал популярную подборку на Github

IT-специалист Джордан Катлер создал и выложил на Github подборку разнообразных ресурсов, которые помогут достичь уровня…

07.12.2023