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

В GLib имеется система обработки исключительных ситуаций называемая GError. В Vala она имеет форму знакомую вам по современным языкам программирования, однако внутренняя реализация существенно отличается от Java и C#. Очень важно понять, когда лучше использовать эту систему - GError специально сделана для обработки некритичных ошибок, то есть факторов, которые не известны до запуска программы и которые не фатальны для продолжения работы. Не следует использовать GError для ошибок, которые можно предвидеть, такие как сообщение о неверном значении переданного методу аргумента. Если, например, методу требуется значение параметра большее нуля, он должен дать ошибку при отрицательных значениях с использованием технических приемов контрактного программирования, таких как предусловия и ассерты, описанные в предыдущем разделе.

Ошибки Vala должны быть где-то обработаны. Однако если вы оставите некоторые ваши ошибки не отловленными, то компилятор выдаст только предупреждение и пройдет дальше.

Использование исключений (или ошибок в терминологии Vala) выражается в:

1\) Объявлении метода, выбрасывающего ошибку:

```csharp
void my_method() throws IOError {
    // ...
}
```

2\) Выбрасывании ошибки:

```csharp
if (something_went_wrong) {
    throw new IOError.FILE_NOT_FOUND("Requested file could not be found.");
}
```

3\) Отлавливании ошибки в вызывающем коде:

```csharp
try {
    my_method();
} catch (IOError e) {
    stdout.printf("Error: %s\n", e.message);
}
```

4\) Сравнивании кодов ошибок с помощью оператора `is`

```csharp
IOChannel channel;
try {
    channel = new IOChannel.file("/tmp/my_lock", "w");
} catch (FileError e) {
    if(e is FileError.EXIST) {
        throw e;
    }
    GLib.error("", e.message);
}
```

Все это выглядит подобно другим языкам, но определение ошибок сильно отличается. Ошибки включают три компонента, известные как "домен", "код" и сообщение. Сообщения вы уже видели - это просто текст, который устанавливается когда создается ошибка. Домен ошибки описывает тип проблемы, и он тождественен классу потомку класса Exception в Java или др. В предыдущих примерах мы видели домен IOError. Третья часть, код ошибки дает точное определение возникшей проблемы. Каждый домен имеет один или несколько кодов ошибок - в том примере это был код "FILE\_NOT\_FOUND" (файл не найден).

Какая информация содержится в каждом типе ошибок зависит от реализации glib. В использованном примере необходимо определение типа:

```coffeescript
errordomain IOError {
    FILE_NOT_FOUND
}
```

Когда вы ловите ошибки, вы указываете домена ошибок, ошибки из которого вы намерены получить, и если выброшена ошибка из указанного домена, то выполняется код обработчика с указанным именем. Из этого объекта ошибки вы можете получить код ошибки и сообщение. Если вы хотите ловить ошибки из другого домена, просто напишите еще один блок catch. Существует так же необязательный блок final, который выполняется после try и catch. Код в этом блоке будет выполнятся всегда, вне зависимости от того, была ошибка или нет, или она была перехвачена и снова выброшена. Это позволяет правильным образом освобождать все ресурсы, выделенные в блоке try. Более полный пример этих возможностей:

```coffeescript
public errordomain ErrorType1 {
    CODE_1A
}

public errordomain ErrorType2 {
    CODE_2A,
    CODE_2B
}

public class Test : GLib.Object {
    public static void thrower() throws ErrorType1, ErrorType2 {
        throw new ErrorType1.CODE_1A("Ошибка");
    }

    public static void catcher() throws ErrorType2 {
        try {
            thrower();
        } catch (ErrorType1 e) {
            // Обработка ErrorType1
        } finally {
            // Освобождаем не нужное
        }
    }

    public static int main(string[] args) {
        try {
            catcher();
        } catch (ErrorType2 e) {
            // Обработка ErrorType1
            if (e is ErrorType2.CODE_2B) {
                // Deal with this code
            }
        }
        return 0;
    }
}
```

Здесь есть два домена ошибок, оба могут быть выброшены методом thrower. Catcher может выбрасывать ошибки только второго типа, поэтому он должен обрабатывать ошибку первого типа, если она выбрасывается thrower'ом. И наконец, метод main будет обрабатывать любые ошибки от catcher'a.<br>


---

# 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://vala.gitbook.io/vala/english/advanced-features/error-handling.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.
