Использование исключений (Руководство по программированию на C#)

В языке C# ошибки в программе во время выполнения передаются через программу посредством механизма, называемого исключениями.Исключения создаются кодом, который встречает ошибку и перехватываются кодом, который может исправить ее.Исключения могут создаваться средой CLR платформы .NET Framework или кодом в программе.В случае исключения, оно передается по стеку вызовов пока не будет найден оператор catch для исключения.Не перехваченные исключения обрабатываются универсальным обработчиком исключений, предоставляемым системой, который открывает диалоговое окно.

Исключения представляются посредством классов, производных от Exception.Такой класс устанавливает тип исключения и содержит свойства с подробными сведениями об исключении.При генерации исключения создается экземпляр класса, производного от исключения, настраиваются свойства исключения (необязательно), а затем при помощи ключевого слова throw создается объект.Примеры.


class CustomException : Exception
{
    public CustomException(string message)
    {

    }

}
private static void TestThrow()
{
    CustomException ex =
        new CustomException("Custom exception in TestThrow()");

    throw ex;
}

После генерации исключения среда выполнения проверяет текущий оператор и устанавливает, находится ли он в блоке try.Все блоки catch (если они имеются), связанные с блоком try, проверяются на возможность обработать исключение.В блоках Catch обычно задаются типы исключений; если тип блока catch совпадает с типом исключения или базовым классом исключения, то блок catch может обработать данный метод.Примеры.

static void TestCatch()
{
    try
    {
        TestThrow();
    }
    catch (CustomException ex)
    {
        System.Console.WriteLine(ex.ToString());
    }
}

Если оператор, создающий исключение, расположен вне блока try или если блок try, в котором он расположен, не имеет соответствующего блока catch, среда выполнения проверяет вызывающий метод на наличие оператора try и блоков catch.Время выполнения продолжается до вызывающего стека в поисках совместимого блока catch.После того, как блок catch найден и выполнен, управление передается следующему оператору после того блока catch.

Оператор try может содержать несколько блоков catch.Выполняется первый оператор catch, который может обработать исключение; все последующие операторы catch, даже если они совместимы – пропускаются.Поэтому необходимо, чтобы блоки catch всегда были упорядочены в порядке от более конкретных (или замыкающих цепочку наследования) к более общим.Примеры.

static void TestCatch2()
{
    System.IO.StreamWriter sw = null;
    try
    {
        sw = new System.IO.StreamWriter(@"C:\test\test.txt");
        sw.WriteLine("Hello");
    }

    catch (System.IO.FileNotFoundException ex)
    {
        // Put the more specific exception first.
        System.Console.WriteLine(ex.ToString());  
    }

    catch (System.IO.IOException ex)
    {
        // Put the less specific exception last.
        System.Console.WriteLine(ex.ToString());  
    }
    finally 
    {
        sw.Close();
    }

    System.Console.WriteLine("Done"); 
}

Перед выполнением блока catch среда выполнения проверяет наличие блоков finally.Блоки Finally позволяют программисту очищать любое неоднозначное состояние, которое могло быть оставлено прерванным блоком try, или освобождать любые внешние ресурсы (например, обработчики графики, подключения к базам данных или потоки файлов), не дожидаясь сборки мусора во время выполнения для завершения объектов.Примеры.

static void TestFinally()
{
    System.IO.FileStream file = null;
    //Change the path to something that works on your machine.
    System.IO.FileInfo fileInfo = new System.IO.FileInfo(@"C:\file.txt");

    try
    {
        file = fileInfo.OpenWrite();
        file.WriteByte(0xF);
    }
    finally
    {
        // Closing the file allows you to reopen it immediately - otherwise IOException is thrown.
        if (file != null)
        {
            file.Close();
        }
    }

    try
    {
        file = fileInfo.OpenWrite();
        System.Console.WriteLine("OpenWrite() succeeded");
    }
    catch (System.IO.IOException)
    {
        System.Console.WriteLine("OpenWrite() failed");
    }
}

Если WriteByte() сгенерировал исключение, код во втором блоке try, пытающийся повторно открыть файл, не будет выполнен, если file.Close() не вызван, и файл останется заблокированным.Так как блоки finally выполняются даже в случае генерации исключения, блок finally в предыдущем примере предусматривает правильное закрытие файла и помогает избежать ошибок.

Если в стеке вызовов после генерации исключения не удается найти совместимый блок catch, то происходит одно из трех действий.

  • Если исключение возникло внутри деструктора, деструктор прерывается и вызывается базовый деструктор, если он имеется.

  • Если в стеке вызовов содержится статический конструктор или статический инициализатор поля, генерируется TypeInitializationException и исходное исключение присваивается свойству InnerException нового исключения.

  • По достижении начала потока он прерывается.

См. также

Ссылки

Исключения и обработка исключений (Руководство по программированию в C#)

Основные понятия

Руководство по программированию на C#