# Обработка ошибок

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

```csharp
private void open_file( string filename ) 
{
  try 
  {
    string text;
    size_t size;
    FileUtils.get_contents( filename, out text, out size );
    this.text_view.buffer.set_text( text, (int) size );
  } 
  catch( Error e ) 
  {
    stderr.printf( "Ошибка: %s\n", e.message );
  }
}
```

В конструкции `try {} catch {}` не видно никаких отличий от аналогов из C++, C# и Java. Особенности обнаруживаются на более низком уровне – в реализации. В библиотеке GLib имеется средство управления исключениями времени выполнения GError. Vala преобразует его в более привычную "современную" форму, но сам по себе GError изначально был предназначен для обработки так называемых восстановимых ошибок времени выполнения, о которых ничего не известно до начала выполнения, и которые не приводят к аварийному завершению программы. Поэтому не следует напрямую использовать GError для тех исключительных ситуаций, которые можно "предсказать", например, передача отрицательного числа в функцию, которая требует параметр только со значением, большим нуля.

При возникновении необходимости в написании специфического кода для обработки исключений общая схема работы точно такая же, как при использовании любого другого языка из "C-группы". Все функции, являющиеся потенциальными источниками исключений, определяются с ключевым словом throws. Везде, где это необходимо в коде, записываются команды генерации исключений throw. Вызовы потенциально "опасных" функций помещаются в блоки try-catch.

Отличия проявляются при определении типов обрабатываемых исключений (ошибок). Исключения обладают тремя характеристиками: домен (domain), код (code) и сообщение (message). Домен определяет тип ошибки. Ближайший аналог – подкласс класса Exception в языке Java. Каждый домен исключения может содержать один или несколько кодов ошибок:

```csharp
errordomain IOError     // имя домена
{
  FILE_NOT_FOUND        // код ошибки
}
```

Таким образом, можно определить не только обобщённый тип возникающей проблемы, но и конкретную ошибку. Что касается сообщений, то мы уже встречались с ними – это текст, выводимый при возникновении исключительной ситуации.

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

Всё, сказанное выше, можно проиллюстрировать следующим примером:

```csharp
errordomain ErrType01
{
  ERROR_CODE_01
}
 
errordomain ErrType02
{
  ERROR_TYPE_02
}
 
public class MyClass : GLib.Object
{
  public static void myfunc_throw() throws ErrType01, ErrType02
  {
    throw new ErrType01.ERROR_CODE_01( "Ошибка с кодом 01" );
  }
 
  public static void myfunc_catch() throws ErrType02
  {
    try
    {
      myfunc_throw();
    }
    catch( ErrType01 e )
    {
      // Здесь обрабатываются ошибки из домена ErrType01
    }
    finally
    {
      // Освобождение ресурсов и прочие необходимые операции
    }
  }
 
  public static int main( string[] args )
  {
    try
    {
      myfunc_catch();
    }
    catch( ErrType02 e )
    {
      // Здесь обрабатываются ошибки из домена ErrType02
    }
    return 0;
  }
}
```

Здесь метод myfunc\_throw может генерировать исключения из обоих доменов, определённых в программе. Метод myfunc\_catch способен генерировать исключения только второго типа, поэтому обязан обеспечить обработку ошибок из домена ErrType01. В свою очередь, метод main обеспечивает обработку всех ошибок, которые могут возникать при работе метода myfunc\_catch.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://nim-ru-tutorial.gitbook.io/ibm-vala-guide/chast-3.-rasshirennye-vozmozhnosti-yazyka-vala/obrabotka-oshibok.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
