2011-01-25 1 views
60

Powiedzmy mamy strukturę tak:Są zagnieżdżone Spróbuj/Catch blokuje zły pomysł?

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 

Widziałem kilka opinii, że gniazdowania Try bloków jak to jest zalecane, ale nie mogłem znaleźć żadnych konkretnych powodów.

Czy to jest zły kod? Jeśli tak, dlaczego?

+2

Nie wiem, jak dokładny jest fragment. Ale nie ma heckofalot, którego naprawdę znasz, kiedy złapiesz wyjątek. Może to być * cokolwiek *. Rozważ zastosowanie klauzuli When, którą obsługuje VB.NET. –

Odpowiedz

63

Są pewne okoliczności, w których są dobrym pomysłem, np. jeden try/catch dla całej metody, a drugi wewnątrz pętli, ponieważ chcesz obsłużyć wyjątek i kontynuować przetwarzanie reszty kolekcji.

Naprawdę jedyny powód, aby to zrobić, to pominąć bit, który ulegał erozji i kontynuować, zamiast rozwijać stos i tracić kontekst. Otwarcie wielu plików w edytorze jest dobrym przykładem.

To powiedziawszy, wyjątki powinny być po prostu wyjątkowe. Program powinien się nimi zajmować, ale starają się ich unikać w ramach normalnego przepływu wykonawczego. Są one kosztowne pod względem obliczeniowym w językach większość języków (python jest godnym uwagi wyjątkiem).

Inną techniką, która może być przydatna łapie konkretne typy wyjątków ...

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 

Jak podkreślił Gooch w komentarzach poniżej, możemy również użyć zagnieżdżone try/połowu w naszych procedurach obsługi błędów .. .

Try 
     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

Logowanie w wątku tła to miejsce, w którym użyję wewnętrznej try/catch. Nie chcę, aby metoda się skończyła, ponieważ nie mogła udokumentować, co robi. – gooch

+0

@Gooch prawda, ja też to robię, dodam to do mojej odpowiedzi. – Basic

31

i rzeczywiście, że nie istnieje coś złego o zagnieżdżonych Try/Catch bloków, oprócz tego, że mogą być trudne w nawigacji i prawdopodobnie znak, że można zrobić kilka refaktoryzacji (wewnętrzna Try/Catch na własną metodę, na przykład).

Ale chcę, aby rozwiązać ten komentarz:

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

Jeśli nie wiesz jak obsługiwać wyjątki w konkretnej sytuacji, zaufaj mi: nie je złapać. Lepiej pozwolić, aby Twoja aplikacja się zawiesiła (to znaczy, wiesz, log to, po prostu nie połykaj), niż złapać coś, czego nie wiesz, jak odzyskać, a następnie pozwól, aby aplikacja nadal była wesoło w drodze uszkodzony stan. Zachowanie będzie w najlepszym wypadku nieprzewidywalne od tego momentu.

+0

To prawda. W momencie wychwycenia zewnętrznego wyjątku nie chciałbym kontynuować. Bardziej myślałem o tym, by móc z przyjemnie zamknąć/ponownie uruchomić aplikację, a nie zaszokować użytkownika "brzydką awarią". – Goro

+9

@Goro: W takim przypadku zaleciłbym mechanizm obsługi wyjątków obejmujący całą aplikację (np. Jeśli jest to WinForms , obsłużyć zdarzenie 'Application.UnhandledException' zamiast bloków" Try "/' Catch' dla poszczególnych metod. –