Jeśli w końcu blok zgłosi wyjątek, co dokładnie się stanie?
W szczególności, co się stanie, jeśli wyjątek zostanie wyrzucony w połowie ostatniego bloku. Czy reszta instrukcji (po) w tym bloku jest wywoływana?
Wiem, że wyjątki będą się rozprzestrzeniać w górę.
c#
exception
exception-handling
try-catch-finally
Jack Kada
źródło
źródło
Odpowiedzi:
Ten wyjątek rozprzestrzenia się w górę i w górę i będzie (można) obsłużyć go na wyższym poziomie.
Twój wreszcie blok nie będzie zostanie ukończony poza punktem, w którym zostanie zgłoszony wyjątek.
Jeśli w końcu blok był wykonywany podczas obsługi wcześniejszego wyjątku, ten pierwszy wyjątek zostanie utracony.
źródło
ThreadAbortException
, cały blok zostanie ostatecznie ukończony, ponieważ jest to sekcja krytyczna.W przypadku takich pytań zwykle otwieram pusty projekt aplikacji konsolowej w programie Visual Studio i piszę mały przykładowy program:
Po uruchomieniu programu zobaczysz dokładną kolejność
catch
ifinally
bloki są wykonywane. Należy pamiętać, że kod w ostatnim bloku po zgłoszeniu wyjątku nie zostanie wykonany (w rzeczywistości w tym przykładowym programie Visual Studio ostrzega cię nawet, że wykrył nieosiągalny kod):Uwaga dodatkowa
Jak zauważył Michael Damatov, wyjątek od
try
bloku zostanie „zjedzony”, jeśli nie poradzisz sobie z nim w (wewnętrznym)catch
bloku. W powyższym przykładzie ponownie zgłoszony wyjątek nie pojawia się w zewnętrznym bloku catch. Aby uczynić to jeszcze bardziej przejrzystym, spójrz na następującą nieznacznie zmodyfikowaną próbkę:Jak widać z danych wyjściowych, wewnętrzny wyjątek został „utracony” (tzn. Zignorowany):
źródło
finally
blok będzie (prawie) zawsze wykonywany, dotyczy to również wewnętrznego bloku na końcu (wystarczy wypróbować sam program przykładowy (Blok na końcu nie zostanie wykonany w przypadku niemożliwego do odzyskania) wyjątek, np.EngineExecutionException
, ale w takim przypadku program i tak zostanie natychmiast zakończony)Jeśli oczekuje się na wyjątek (gdy
try
blok ma znak „finally
ale nie”catch
), nowy wyjątek zastępuje ten wyjątek.Jeśli nie ma oczekującego wyjątku, działa on tak jak wyrzucenie wyjątku poza
finally
blok.źródło
catch
blok że (ponownie) wyrzuca wyjątek.Wyjątek jest propagowany.
źródło
Szybki (i raczej oczywisty) fragment, aby zapisać „oryginalny wyjątek” (wrzucony w
try
bloku) i poświęcić „w końcu wyjątek” (wrzucony wfinally
bloku), na wypadek gdyby oryginalny był dla Ciebie ważniejszy:Po wykonaniu powyższego kodu „Original Exception” propaguje stos wywołań, a „Last Exception” zostaje utracony.
źródło
Musiałem to zrobić, aby wychwycić błąd podczas próby zamknięcia strumienia, który nigdy nie został otwarty z powodu wyjątku.
jeśli webRequest został utworzony, ale podczas połączenia wystąpił błąd połączenia
wtedy w końcu wychwyciłby wyjątek próbujący zamknąć połączenia, które według niego były otwarte, ponieważ utworzono webRequest.
Gdyby w końcu nie było w środku try-catch, ten kod spowodowałby nieobsługiwany wyjątek podczas czyszczenia webRequest
stamtąd kod zakończyłby działanie bez prawidłowej obsługi występującego błędu, a tym samym powodując problemy dla metody wywołującej.
Mam nadzieję, że to pomoże jako przykład
źródło
Zgłoszenie wyjątku, gdy aktywny jest inny wyjątek, spowoduje zastąpienie pierwszego wyjątku drugim (późniejszym) wyjątkiem.
Oto kod ilustrujący to, co się dzieje:
źródło
Kilka miesięcy temu spotkałem się z czymś takim,
Aby rozwiązać taki problem, stworzyłem klasę użyteczności jak
I używane w ten sposób
ale jeśli chcesz używać parametrów i zwracać typy, to inna historia
źródło
Sposób obsługi wyjątków zgłaszanych przez CodeA i CodeB jest taki sam.
Wyjątek zgłoszony w
finally
bloku nie ma nic specjalnego, potraktuj go jak wyjątek wygenerowany przez kod B.źródło
Wyjątek rozprzestrzenia się w górę i powinien być obsługiwany na wyższym poziomie. Jeśli wyjątek nie jest obsługiwany na wyższym poziomie, aplikacja ulega awarii. Wykonywanie bloku „w końcu” kończy się w momencie zgłoszenia wyjątku.
Niezależnie od tego, czy istnieje wyjątek, czy blok „nareszcie” jest gwarantowany do wykonania.
Jeśli blok „w końcu” jest wykonywany po wystąpieniu wyjątku w bloku try,
a jeśli ten wyjątek nie zostanie obsłużony
a jeśli w końcu blok zgłosi wyjątek
Następnie oryginalny wyjątek, który wystąpił w bloku try, zostaje utracony.
Świetny artykuł dla szczegółów
źródło
Zgłasza wyjątek;) Możesz złapać ten wyjątek w innej klauzuli catch.
źródło