2013-10-16 7 views
6

VB.NET ma, w przeciwieństwie do C#, funkcję warunkowego wychwytywania wyjątków w bloku Try/Catch/Finally.VB.NET Try/Catch/When - Trzymaj się z daleka, czy może z niego korzystać?

Wydaje mi się, że czytałem gdzieś, że jest to zwykle zła praktyka, ponieważ zachęca ludzi do umieszczenia logiki biznesowej w mechanizmie obsługi wyjątków i że zasadniczo kończy się to uwielbieniem GoTo.

Try 
    // Do something 
Catch ex As MyException When [condition] 
    // 
End Try 

Więc są tam legit przypadki korzystania z funkcji When lub powinniśmy trzymać się z dala od niego?

Prawdopodobnie zostało to już udzielone, ale nie udało mi się znaleźć niczego istotnego, ponieważ słowo "kiedy" było niezłym słowem kluczowym dla wyszukiwania.

+0

Może warto edit podkreślić, że filtry wyjątków są dostępne w języku C# teraz (w przeciwieństwie do pierwszego zdania w pytaniu) –

Odpowiedz

5

Typowy przypadek, jaki przychodzi mi na myśl, to sytuacja, w której chcesz uchwycić określony wyjątek na podstawie treści tego wyjątku. Np .:

Try 
    // Do something 
Catch ex As SqlException When ex.Number = 547 
    // Constraint Violation 
End Try 

co pozwala zaoszczędzić od przechwytywania wszystkieSqlException s, następnie bada właściwość Number, a następnie konieczności ponownego rzucić wyjątek, jeśli nie pasuje.

Zobacz także The good and bad of exception filters:

Na przykład, jeśli masz dość ogólny wyjątek, jak COMException, zazwyczaj tylko chcą złapać że gdy reprezentuje pewną HRESULT. Na przykład, chcesz pozwolić mu odejść nieobsługiwanym, gdy reprezentuje E_FAIL, ale chcesz go złapać, gdy reprezentuje E_ACCESSDEINED, ponieważ masz alternatywę dla tego przypadku. Tutaj jest to całkowicie uzasadnione warunkowe klauzula catch:

Catch ex As System.Runtime.InteropServices.COMException When ex.ErrorCode() = &H80070005 

Alternatywą jest umieszczenie warunku w bloku catch i przekaż wyjątek, jeśli nie spełniają podane kryteria. Na przykład:

Catch ex As System.Runtime.InteropServices.COMException 
    If (ex.ErrorCode != &H80070005) Then Throw 

Logicznie rzecz biorąc, to „haczyk/rethrow” wzór robi to samo, podobnie jak filtr, ale jest subtelna i istotna różnica. Jeśli wyjątek zostanie nieobsługiwany, stan programu będzie się różnił między tymi dwoma. W przypadku catch/rethrow, nieobsługiwany wyjątek wydaje się pochodzić z instrukcji Throw w bloku catch. Nie będzie żadnego stosu połączeń poza tym, a wszystkie ostatecznie bloki do klauzuli catch zostaną wykonane. Oba utrudniają debugowanie. W przypadku filtru wyjątek jest nieobsługiwany od punktu oryginalnego rzutu, a żaden stan programu nie został zmieniony przez zdania końcowe.

+0

FWIW ... Moje rozumienie jest tych wszystkich innych rzeczy (łapanie oryginalny, badając liczba, ponowne rzucanie) nadal się zdarzają. Chodzi o to, że kod, który zachowujesz, nie musi zajmować się nim bezpośrednio. –

+0

@JoelCoehoorn - Filtry wyjątków są wbudowane w mechanizm obsługi wyjątków CLR. To nie tak, że kompilatory VB (i C# teraz) faktycznie wstawiają ten kod. Filtry wyjątków w rzeczywistości wczytują się wcześniej niż jakakolwiek ręczna obsługa (np.oni faktycznie strzelają * przed * jakimiś wewnętrznymi klauzulami "w końcu" działają) –

Powiązane problemy