- Централизирано
обработване на грешки
Можем да насочим обработката на
грешката към централно, обработване на грешките:
On
Error Goto label
Ето и скелет на код:
Sub
Example( )
On
Error Goto ErrHandler
'' ако се случат грешки
при изпълнение: run-time error
'' Visual Basic директно
се обръща към ErrHandler
Exit
Sub
ErrHandler:
'' код за обработка на
грешки
'' или подаването им към
списък - calls list.
End
Sub
След като ред On Error Goto label се изпълни, казваме, че
започването на манипулатор на грешка (error handler) на етикет ErrHandler е активно (active).
Има няколко възможности за
обработване на грешката. Най-честия е може би да се изведе съобщение и да се пита
потребителя за коригираща акция.
Друг общ способ е подаването на
информация за грешката към викащата процедура с параметри или с върната
стойност от приключващата функция (offending function). Например, ако функцията е проектирана да
преименова файл, функцията може да връща цяло число като код за индикиране на грешката или за показване на успеха на
операцията . Би трябвало
кодът за грешка (error code) да е 0 за успешна операция, -1 ако файлът не съществува, -2 ако новото име на файла е
невалидно и т.н.
Третата възможност е да подадем
грешката на викащата процедура чрез метод Err.Raise извикан вътре в активния манипулатор
на грешка (error handler):
Err.Raise(Err.Number,
Err.Source, Err.Description, _
Err.HelpFile,
Err.HelpContext)
Този процес се нарича
регенериране на грешка (regenerating или reraising).
Може да се деактивира активния манипулатор
на грешка (error handler) така:
On
Error Goto 0
Ако няма активен манипулатор на
грешка (error handler), тогава VB реагира
така и ние ще опишем тази реакция в следващата точка.
- Няма манипулатор на грешка
(error-handler)
Ако няма error handler в процедурата offending
procedure, защото няма инструкция OnError в процедурата или защото е
деактивиран с On Error Goto 0 инструкция , Visual Basic автоматично праща грешката към error handler на викащата (calling) процедура. Ако и викащата
процедура няма error handler, грешката продължава по списъка на
виканията, за да открие такъв (error handler). Ако не се намери, Visual Basic обработва
грешката като показва съобщение и прекъсва изпълнението на апликацията.
8.2.2 Структурирано обработване на грешки - Structured Exception
Handling
То използва структурата Try...Catch...Finally за да обработи
грешките. Както можем да се уверим, VB .NET's структурираното
обработване на
грешки е много повече обектно-ориентирано, включващо обектите на класа Exception class и неговите произхождащи класове.
- Try...Catch...Finally
Синтаксис на Try...Catch...Finally конструкцията:
Try
tryStatements
[Catch1
[exception [As type]] [When expression]
catchStatements1
[Exit
Try]
Catch2
[exception [As type]] [When expression]
catchStatements2
[Exit
Try]
. . .
Catchn
[exception [As type]] [When expression]
catchStatementsn]
[Exit
Try]
[Finally
finallyStatements]
End
Try
Инструкция tryStatements
(която се
изисква) конституира блока Try където са инструкциите мониториращи за
грешки при VB. Вътре в блок Try, казваме, че обработването на
грешки е активно (active).
Блоковете Catch съдържат кода, който изпълнява отговора на VB "хващането" на отделните грешки вътре в блок Try. Така, блоковете Catch
се състоят от
манипулатори на грешки (error-handlers) за
блок Try.
Фразите exception
[As type] и [When expression] са свързани с филтрите (filters) във
VB .NET документацията. В първия случай, exception
е или променлива
от тип Exception, който е базовия
клас, който "хваща" всички
изключения, или променлива на един от произхождащите класове от Exception. Примерно променливата
декларирана като:
Catch
e As Exception
ще хване всяка грешка. Променливата декларирана като:
Catch
e As ArgumentNullException
ще хване всяка грешка от клас ArgumentNullException. Накратко, type
е името на един
от класовете Exception.
Филтърът When типично се използва с
потребителски-дефинирани грешки. Кодът в следния Try блок вдига грешка, ако
потребителят не въведе число. Блокът Catch хваща тази грешка:
Try
Dim
sInput As String
sInput
= Inputbox("Enter a number.")
If
Not IsNumeric(sInput) Then
Err.Raise(1)
End
If
Catch
When Err.Number = 1
Msgbox("Error1")
End
Try
Забележете, че такъв код:
Dim
x As Integer
Try
x
= 5
Catch
When x = 5
MsgBox(x)
End
Try
не работи (инструкция Catch никога няма да се изпълни) защото не е генерирана грешка.
Инструкция Exit Try се използва за прекъсване на всяка порция код на Try...Catch...Finally блок. Опционалния блок код finallyStatements
се изпълнява
независимо дали се появява грешката (или
е хваната), независимо
дали инструкция Exit Try е изпълнена. Този финален код може да се използва за изчистване в
събитието на грешката . (При написването на Exit Try в края на блок Try, блокът finallyStatements не се изпълнява, ако не се появи грешка.)
VB може да подаде грешка към call стека, когато обработва струкурирано
грешки, както при неструстурирано. Това се случва при следните ситуации:
· Ако грешката се появи вътре в
блок Try, който не е обработен от съществуващия Catch блок
· Ако грешката се появи извън всеки блок Try (обезпечавайки разбира
се, че няма активни On Error-манипулатори на стилните грешки).
Пример:
Dim
x, y As Integer `двете са челочислени - integers
Try
x
= y ` деление на нула
Catch
ex As Exception
msgbox(ex.Message)
End
Try
Забележка
Частта ex As Exception от
инструкция Catch е опционална. Тук имаме две целочислени променливи (integers). При опита за
деление x на y се получава грешка от деление на нула, защото y не е
инициализирано и е по подразбиране 0. Делението на нула вдига грешка, която
хващате в следващия ред. Променливата ex е от тип Exception, който държи току що появилата се грешка и
вие просто принтирате свойство Message,
както правите с Err.Description във VB6.
Фактически, можете да използвате Err.Description, и обект Err . Обект Err ще
изтегли всяко изключение, което се е появило. Нека в даден пример, да се вдига
продиктувана от логиката грешка, която регистрира ако на някой баланса на
сметката му е много нисък, а друга грешка ако баланса му е отрицателен:
Try
If
bal < 0 Then
Throw
New Exception("Balance is negative!")
ElseIf
bal > 0 And bal <= 10000 Then
Throw
New Exception("Balance is low; charge interest")
End
If
Catch
MessageBox.Show("Error:
" & Err().Description)
Finally
MessageBox.Show("Executing
finally block.")
End
Try
В този случай, бизнес логиката ви диктува, ако на някой
баланса клони към нула, да вдигате грешка,
информираща за това. Ако баланса е около 10,000 но се задържа над нулата, вие осведомявате потребителя да започне да
олихвява. В този
случай, Err().Description улавя обяснението, което сте прехвърлили във
вашето Exception.
Може да имате много оператори Catch, за да прихващате различни грешки. За да може оператор Catch да хваща конкретна грешка, трябва да прибавите клауза When към този Catch.
Пробвайте кода:
Try
x
= y `
Catch
ex As Exception When Err().Number = 11
MsgBox("You
tried to divide by zero")
Catch
ex As Exception
MsgBox("Acts
as catch-all")
End
Try
В този пример проверяваме за грешка Err().Number равна на 11, която е грешка при деление с нула. Ако се появи
друга грешка, ще се хване от Catch без клауза When. Ефектът на Catch без When е като "else".
Кодът не минава през всички изключения (exceptions); спира на първата грешка,
която намира.
Ако искате да върви някакъв код накрая,
независимо от откритата грешка, (или ако не
е открита такава),
вие трябва да прибавите оператор Finally:
Try
x
= y ` cause division by zero
Catch
ex As Exception When Err().Number = 11
MsgBox("You
tried to divide by zero")
Catch
ex As Exception
MsgBox("Acts
as catch-all")
Finally
MsgBox("Running
finally code")
End
Try
В този код секция Finally ще се изпълни.
Да излезем (exit) от оператор Try по-рано. Ключова дума Exit Try както вече казахме е предвидена за
прекъсване на блок Try по-рано, игнорирайки Finally.
Синтаксисът е:
Try
x
= y ` деление на нула
Catch
ex As Exception When Err.Number = 11
msgbox("You
tried to divide by zero")
Exit
Try
Catch
ex As Exception
msgbox("Acts
as catch-all")
Finally
msgbox("Running
finally code")
End Try