Чи є вкладені блоки Try / Catch поганою ідеєю?


83

Скажімо, у нас така структура:

Try
  ' Outer try code, that can fail with more generic conditions, 
  ' that I know less about and might not be able to handle

  Try
    ' Inner try code, that can fail with more specific conditions,
    ' that I probably know more about, and are likely to handle appropriately
  Catch innerEx as Exception
    ' Handle the inner exception
  End Try

Catch outerEx as Exception
  ' Handle outer exception
End Try

Я бачив деякі думки, що вкладати Tryтакі блоки не рекомендується, але я не міг знайти конкретних причин.

Це поганий код? Якщо так, то чому?


2
Не впевнений, наскільки точно є фрагмент. Але немає такого гекофалота, якого ви справді знаєте, коли ловите виняток. Це може бути що завгодно . Подумайте про використання пропозиції When, яку підтримує VB.NET.
Hans Passant

Відповіді:


86

Існують певні обставини, коли вони є гарною ідеєю, наприклад, одна спроба / зловити для цілого методу, а інша всередині циклу, коли ви хочете обробити виняток і продовжити обробку решти колекції.

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

Тим не менш, винятки повинні (як випливає з назви) бути винятковими. Програма повинна обробляти їх, але намагатися уникати їх як частину звичайного потоку виконання. Вони обчислювально дорогі в більшості мов (Python є одним з помітних винятків).

Ще одна техніка, яка може бути корисною, - це ловити конкретні типи винятків ...

Try
    'Some code to read from a file

Catch ex as IOException
    'Handle file access issues (possibly silently depending on usage)
Catch ex as Exception
    ' Handle all other exceptions.
    ' If you've got a handler further up, just omit this Catch and let the 
    ' exception propagate
    Throw
End Try

Ми також використовуємо вкладені спроби / лови в наших процедурах обробки помилок ...

    Try
        Dim Message = String.Format("...", )
        Try
            'Log to database
        Catch ex As Exception
            'Do nothing
        End Try

        Try
            'Log to file
        Catch ex As Exception
            'Do nothing
        End Try
    Catch ex As Exception
        'Give up and go home
    End Try

7
Вхід у фоновий потік - це місце, де я буду використовувати внутрішню спробу / лову. Я не хочу, щоб метод закінчувався, оскільки він не міг задокументувати те, що робив.
gooch

@Gooch правда, я теж це роблю, додаю це до своєї відповіді.
Basic

37

Насправді я не думаю, що в вбудованих Try/ Catchблоках є щось по суті неправильне , за винятком того, що в них може бути важко орієнтуватися і, швидше за все, є ознакою того, що ви могли б зробити деякий рефакторинг (наприклад, внутрішній Try/ Catchу свій власний метод).

Але я хочу звернутися до цього коментаря:

' Outer try code, that can fail with more generic conditions, 
' that I know less about and might not be able to handle

Якщо ви не знаєте, як обробляти винятки в конкретній ситуації, повірте мені: не ловіть їх. Краще дозволити своєму додатку вийти з ладу (я маю на увазі, ви знаєте, зареєструйте його; просто не ковтайте його), ніж ловити те, від чого не знаєте, як відновитись, а потім нехай ваш додаток весело продовжує свій шлях у пошкодженому стані . З цього моменту поведінка буде в кращому випадку непередбачуваною.


Це правда. На етапі лову зовнішнього винятку я не хотів би продовжувати. Я більше думав про те, щоб можна було вимкнути / перезапустити програму витончено, а не шокувати користувача "потворним збоєм"
Горо,

10
@Goro: У такому випадку я б рекомендував загальнодоступний механізм обробки винятків (наприклад, якщо це WinForms, обробляти Application.UnhandledExceptionподію), а не по методу Try/ Catchблокам.
Dan Tao
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.