Обзор синтаксиса операторов try, catch и finally

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

Рассмотрим пример оператора try:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
using System;
using System.Collections;
using System.Runtime.CompilerServices;
// Отключить предупреждение компилятора: CS1058
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = false)]
public class EntryPoint {
static void Main()  {
try {
ArrayList list = new ArrayList();
list.Add( 1 ) ;
Console.WriteLine( "Элемент 10 = {0}", list[10] );
}
catch( ArgumentOutOfRangeException x )  {
Console.WriteLine( "=== Обработчик ArgumentOutOfRangeException"+
II    ___H     )   .
Console.WriteLine ( x );
Console.WriteLine ( "=== Обработчик
ArgumentOutOfRangeException"+
" ===\n\n" ) ;
}
catch ( Exception x )  {
Console.WriteLine ( "=== Обработчик исключения ===" );
Console.WriteLine ( x );
Console.WriteLine ( "=== Обработчик исключения ===\n\n" );
}
catch {
Console.WriteLine( "=== Необработанное исключение" +
" Handler ===" ) ;
Console.WriteLine( "Исключение, которое не" +
" ожидалось..." ) ;
Console.WriteLine( "=== Необработанное исключение" +
" Handler ===" ) ;
}
finally {
Console.WriteLine ( "Очистка..." );
}
}
}

Код внутри блока try предназначен для генерации исключения ArgumentOutOf Range Exception. Как только исключение сгенерировано, исполняющая система начинает поиск подходящей конструкции catch, являющейся частью этого оператора try и максимально соответствующей типу исключения. Ясно, что лучше всего подходит первая конструкция catch. Поэтому исполняющая система немедленно начинает выполнение операторов из первого блока catch.

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

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

Вторая конструкция catch будет перехватывать исключения общего типа Exception. Если код в блоке try сгенерирует исключение, производное от System. Exception и отличающееся от ArgumentOutOfRangeException, то этот второй блок catch обработает его.

В С# множественные конструкции catch, ассоциированные с одним блоком try, должны следовать в таком порядке, чтобы наиболее специфичные исключения обрабатывались первыми. Код, в котором общие конструкции catch предшествуют более специфичным, просто не скомпилируется. В этом легко убедиться, поменяв местами первые две конструкции catch в предыдущем примере — будет выдано следующее сообщение об ошибке:

error CS0160: A previous catch clause already catches all exceptions of this or of a super type (’System. Exception 1)
ошибка CS0160: Предыдущая конструкция catch уже перехватила все исключения этого типа или его супертипа (System.Exception)

В С# каждое исключение, которое можно сгенерировать, должно наследоваться от System.Exception. Поскольку объявлена конструкция catch, специально предназначенная для исключений типа System.Exception, как насчет третьей и последней конструкции catch? Несмотря на то что сгенерировать исключение типа, не унаследованного от System.Exception, в языке С# невозможно, это не является невозможным для среды CLR. Например, в языке С++ можно сгенерировать исключение любого типа.

Поэтому если написать ArrayList на языке, который позволяет это, может получиться, что код сгенерирует исключение не очень полезного типа, такого как System.Int32. Звучит странно, но такое возможно. В этом случае можно перехватить такое исключение в С#, применив блок catch без явного типа исключения и без переменной. К сожалению, при этом не существует простого способа узнать тип сгенерированного исключения. К тому же оператор try может иметь максимум одну общую конструкцию catch без аргументов.

Начиная с версии .NET 2.0, ситуация с общими конструкциями catch стала немного отличаться от .NET 1.1. Появился новый атрибут RuntimeCompatibilityAttribute, который можно присоединить к сборке. Компиляторы С# и Visual Basic, ориентированные на .NET 2.0, применяют это свойство по умолчанию.

Это говорит исполняющей системе о том, что исключения, не унаследованные от System.Exception, должны быть помещены в оболочку RuntimeWrappedException, которая наследуется от System.Exception. Это удобно, поскольку позволяет коду С# получить доступ к сгенерированному исключению. Ранее доступ к сгенерированному исключению был невозможен, поскольку оно перехватывалось общим, лишенным параметров, блоком catch.

Теперь с помощью свойства RuntimeWrappedException. WrappedException можно получить доступ к действительному типу сгенерированного исключения. Если код содержит блок catch без параметров, компилятор по умолчанию выдает предупреждение CS1058. Вывод этого предупреждения можно отключить, как было показано в предыдущем примере.

В самом конце находится блок finally. Независимо от того, как произошел выход из блока try — по достижении его конечной точки, через генерацию исключения или оператор return — блок finally выполняется всегда. Если есть подходящий блок catch и блок finally, ассоциированный с тем же самым блоком try, блок catch выполняется перед блоком finally. В этом легко убедиться, взглянув на вывод предыдущего кода примера, который выглядит следующим образом:

=== Обработчик ArgumentOutOfRangeException -==
System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: index

System. ArgumentOutOf RangeException: Выход индекса за допустимые пределы. Должен быть неотрицательным и меньше размера коллекции. Имя параметра: index

at System.Collections.ArrayList.get_Item(Int32 index)
at Entrypoint.Main()
=== Обработчик ArgumentOutOfRangeException ===
Очистка…

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

1 комментарий »

 
  • baxa says:

    Пожалуйста подскажите.
    Скрипт на сайте выполняет заданную операцию верно. То есть при регистрации нового пользователя (регистрация происходит верно), однако при этом выдается еще и следующая ошибка “Warning: mysql_num_rows(): supplied argument is not a valid MySQL result resource in /home/88*888/public_html/inc/register.inc on line 73”
    Как для такого случая поставить блок try &

 

Оставьте отзыв

XHTML: Вы можете использовать следующие теги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

 
Rambler's Top100