Как правильно поднимать ошибки из класса - PullRequest
0 голосов
/ 06 июня 2018

У меня вопрос: как правильно вызвать ошибки в классе, чтобы вызывающий объект, который создает экземпляр этого класса, мог использовать правильные методы обработки ошибок?

Я обновляю старый код спагетти VB6, который неиспользовать классы.В прошлом я всегда использовал On Error Resume Next и On Error Перейти к myLabel для устранения ошибок, когда альтернативы не былилюбой очиститель для моего кода.

Однако я не могу заставить вызывающего обработать ошибки, потому что, если я вызываю ошибку в методе или свойстве моего класса, ошибка возникает независимо от того, использовал ли я On Error оператор, чтобы поймать его от вызывающей стороны.Пример кода будет выглядеть примерно так:

MyClass:

Public Sub Bar()
    If valid Then
        'some code here
    Else
        Err.Raise 5
    End if
End Sub

MainForm:

Private Sub CallFoo()
    Dim foo as New MyClass

    On Error Goto fooliure 'Starts ignoring errors
    Call foo.Bar() 'Program stops with an exception
    On Error Goto 0 'Ends error handling

    Exit Sub
    fooliure:
        'Error handling code
End Sub

Также Microsoft говорит, что именно так они и собирались обрабатывать ошибкибыть выполненным в VB 6.0, как упомянуто здесь .

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

1 Ответ

0 голосов
/ 14 июня 2018

Дэвид, вот краткое руководство по обработке ошибок VBA 101.

  • Err объект.Это одноэлементный объект, который содержит текущую ошибку.Не пытайтесь создать экземпляр этого объекта (т.е. не используйте Set objErr = New Err - это не удастся)
  • On Error - установить обработку ошибок.Возможные обработчики ошибок:
    • On Error GoTo Label - Выполнение переходит на Label при возникновении ошибки
    • On Error Resume Next - Выполнение переходит на следующую строку при обнаружении ошибки
    • On Error GoTo 0 - отключает текущий обработчик ошибок.Любые последующие ошибки будут обработаны вызывающим
    • On Error Resume - Выполнение переходит на строку, вызвавшую ошибку (не рекомендуется)
  • Объект Errочищается (теряет текущую ошибку), когда:
    • Подпрограмма, функция или свойство вызывается
    • Подпрограмма, функция или свойство обычно завершаются
    • Выполняется оператор On Error
    • Err.Clear сбрасывает текущую ошибку при вызове
  • Повышение исключений.Вы можете выдавать ошибки в любое время.Каноническая форма:

    Err.Raise 1001 + vbObjectError, Description:="An exception occurred."
    
  • Пользовательские ошибки: используйте vbObjectError, чтобы сделать пользовательскую ошибку.Пример:
    • 1001 + vbObjectError
    • Целочисленный диапазон от 0 до 65535
  • Последовательность обработки ошибок:
    1. Если естьЛокальный обработчик ошибок, определенный в подпрограмме, выполняет его
    2. Если локального обработчика нет, выдает ошибку вызывающей стороне
    3. Если у вызывающей стороны нет обработчика, он продолжает выдавать ошибку до локальногоОбнаружен обработчик
    4. Если обработчик верхнего уровня отсутствует, приложение завершает работу
  • Создание цепочек ошибок.Очень полезно создавать цепочки ошибок, которые показывают исходную ошибку, и отображают список подпрограмм в стеке при возникновении ошибки.Для этого:
    • Добавить обработку ошибок к каждой подпрограмме, которая может вызвать ошибку
    • Всегда повторно вызывать ошибку для вызывающей стороны
    • Добавитьстрока Err.Source с именем процедуры при повторном возникновении ошибки
    • Процедура вызова верхнего уровня может использовать MsgBox для информирования пользователя об ошибке (или может быть реализована другая регистрация)

Вот пример кода, демонстрирующий эти идеи:

Public Sub TestErrorLevel1()

    On Error GoTo HandleErr ' clears Err object

    TestErrorLevel2

    Exit Sub

HandleErr:
    ' top-level error handler -- nothing else to raise error to
    ' show error and complete call chain
    MsgBox "Error: " & Err.Number & vbCrLf & Err.Description & vbCrLf _
        & "Source: modTest.TestErrorLevel1" & vbCrLf & Err.Source
End Sub

Public Sub TestErrorLevel2()

    On Error GoTo HandleErr ' clears Err object

    TestErrorLevel3

    Exit Sub

HandleErr:
    ' re-raise error, adding this subroutine to call chain
    Err.Raise Err.Number, "modTest.TestErrorLevel2" & vbCrLf & Err.Source, Err.Description
End Sub

Public Sub TestErrorLevel3()

    On Error GoTo HandleErr ' clears Err object

    Err.Raise 1001 + vbObjectError, Description:="User-defined error. Offset range from 0 to 65535"

    Exit Sub

HandleErr:
    ' re-raise: add module and routine to originating error
    Err.Raise Err.Number, "modTest.TestErrorLevel3" & vbCrLf & Err.Source, Err.Description
End Sub
...