Повторная генерация и трансляция исключений

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

Для реализации сказанного используется оператор throw без параметров:

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
using System;
using System.Collections;
public class Entrypoint
{
static void Main()  {
try {
try {
ArrayList list = new ArrayList ();
list. Add ( 1 ) ;
Console.WriteLine( "Элемент 10 = {0}", list[10] );
}
catch( ArgumentOutOfRangeException )  {
Console.WriteLine ( "Выполнить полезную работу и" +
" повторить исключение" );
// Заново сгенерировать перехваченное исключение, throw;
}
finally {
Console.WriteLine ( "Очистка..." );
}
}
catch {
Console.WriteLine ( "Готово" );
}
}
}

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

Выполнить полезную работу и повторить исключение
Очистка…
Готово

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

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

Иногда необходимо “транслировать” исключение внутри обработчика исключений. В этом случае перехватывается исключение одного типа, но затем генерируется исключение другого типа — возможно, более точного — в блоке catch для передачи его на обработку на следующем уровне.

Рассмотрим приведенный ниже пример:

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
using System;
using System.Collections;
public class MyException : Exception
{
public MyException ( String reason. Exception inner ) :base( reason, inner )  {
}
}
public class Entrypoint {
static void Main()  {
try {
try {
ArrayList list = new ArrayList ();
list. Add ( 1 ) ;
Console.WriteLine( "Элемент 10 = {0}", list[10] );
}
catch( ArgumentOutOfRangeException x )  {
Console.WriteLine ( "Выполнить полезную работу и " + " повторить исключение" );
throw new MyException ( "Лучше сгенерировать исключение", х ) ;
}
finally {
Console.WriteLine( "Очистка..." );
}
}
catch ( Exception x )  {
Console.WriteLine ( x );
Console.WriteLine ( "Готово" );
}
}
}

Одним особым качеством типа System.Exception является способность включать в себя ссылку на вложенное исключение через свойство Exception. InnerException. Таким образом, когда генерируется новое исключение, вы можете предохранить цепочку исключений для исключений, обрабатывающих их. Я рекомендую использовать это полезное свойство стандартного типа исключений С# для трансляции ваших исключений.

Вывод предыдущего кода выглядит следующим образом:

Выполнить полезную работу и повторить исключение
Очистка…
MyException: Лучше сгенерировать исключение —> System.ArgumentOutOfRangeException:
Index was out of range.
Must be non-negative and less than the size of the collection.
Parameter name: index
at System.Collections.ArrayList.get_Item(Int32 index)
at Entrypoint.Main()
– End of inner exception stack trace
at Entrypoint.Main()

System.ArgumentOutOfRangeException:
Выход индекса за пределы диапазона.
Значение должно быть положительным и меньше размера коллекции.
Имя параметра: index
в System.Collections.ArrayList.get_Item (Int32 index)
в Entrypoint.Main ()
– Конец трассировки стека внутреннего исключения
–в Entrypoint.Main()

Готово

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

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

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

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

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