Do czego służy wyjątek ApplicationException w .NET?

172

Rzucać wyjątki, zazwyczaj użyć wbudowanych klas wyjątków, np ArgumentNullExceptiona NotSupportedException. Czasami jednak potrzebuję użyć niestandardowego wyjątku iw takim przypadku piszę:

class SlippedOnABananaException : Exception { }
class ChokedOnAnAppleException : Exception { }

i tak dalej. Następnie wrzucam i łapię je w moim kodzie. Ale dzisiaj natknąłem się naApplicationException klasę - czy powinienem zamiast tego używać? Do czego to służy?

Wydaje się nieefektywne, aby mieć wiele skutecznie identycznych klas wyjątków o różnych nazwach (zwykle nie potrzebuję żadnej indywidualnej funkcjonalności). Ale nie podoba mi się pomysł łapania leku generycznegoApplicationException i konieczności użycia dodatkowego kodu, aby określić, jaki był błąd.

Gdzie powinien ApplicationExceptionpasować mój kod?

James
źródło
35
Świetne pytanie, także +1 za sprytnie nazwane przykładowe wyjątki
Cody Gray

Odpowiedzi:

100

Zgodnie z uwagami w msdn:

Aplikacje użytkownika, a nie środowisko uruchomieniowe języka wspólnego, generują niestandardowe wyjątki pochodzące z klasy ApplicationException. Klasa ApplicationException rozróżnia wyjątki zdefiniowane przez aplikacje od wyjątków zdefiniowanych przez system.

Jeśli projektujesz aplikację, która musi tworzyć własne wyjątki, zaleca się wyprowadzenie wyjątków niestandardowych z klasy Exception. Początkowo sądzono, że wyjątki niestandardowe powinny pochodzić z klasy ApplicationException; jednakże w praktyce nie okazało się, że wnosi to znaczącą wartość. Aby uzyskać więcej informacji, zobacz Najważniejsze wskazówki dotyczące obsługi wyjątków.

Wyprowadź je z Exception. Nie widzę też problemu z tworzeniem nowych wyjątków dla Twoich spraw, o ile jest to uzasadnione. Jeśli napotkasz przypadek, w którym istnieje już wyjątek we frameworku, użyj go, w przeciwnym razie rzuć własny.

Femaref
źródło
9
Więc wydaje się, że ApplicationExceptionjest to bezużyteczne i czy istnieje tylko z powodu wstecznej kompatybilności?
Beatles1692
Nowa dokumentacja MSDN, przynajmniej 4.7.2, pomija tę uwagę. Dzięki za qutoe: D
Alex
147

Krótka odpowiedź brzmi: nigdzie.

Jest to relikt przeszłości, w której Microsoft chciał, aby programiści odziedziczyli wszystkie niestandardowe wyjątki od ApplicationException. Wkrótce zmienili zdanie i doradzili, że wyjątki niestandardowe powinny pochodzić z podstawowej klasy Exception. Zobacz najlepsze rozwiązania dotyczące obsługi wyjątków w witrynie MSDN.

Jednym z bardziej rozpowszechnionych powodów takiego stanu rzeczy jest fragment Jeffery Richter w Framework Design Guidelines :

System.ApplicationException to klasa, która nie powinna być częścią platformy .NET Framework. Pierwotny pomysł polegał na tym, że klasy wywodzące się z SystemException wskazywałyby wyjątki wyrzucane z samego środowiska CLR (lub systemu), podczas gdy wyjątki inne niż CLR byłyby wyprowadzane z ApplicationException . Jednak wiele klas wyjątków nie było zgodnych z tym wzorcem. Na przykład TargetInvocationException (który jest generowany przez środowisko CLR) pochodzi z ApplicationException . Tak więc klasa ApplicationException straciła wszelkie znaczenie. Powodem wyprowadzenia z tej klasy bazowej jest umożliwienie niektórym kodom znajdującym się wyżej na stosie wywołań, aby przechwycić klasę bazową. Nie było już możliwe wychwycenie wszystkich wyjątków aplikacji.

Więc masz to. Podsumowanie jest takie, że ApplicationException nie jest szkodliwy , po prostu bezużyteczny .

Szybki Joe Smith
źródło
2
Czy ktoś wie, dlaczego tak jest? Wygląda na to, że miałoby sens wyświetlenie wyjątków aplikacji, ale nie wyjątków „spieprzony programista”.
Josh Kodroff
9
Przy okazji, z tego wyjaśnienia wynika, że ​​nie jest to zły projekt jako taki, ale MSFT schrzanił implementację. Czy ktoś jeszcze czytał to podobnie?
Josh Kodroff,
8
@JoshKodroff: Myślę, że problem polega na tym, że jeśli aplikacja Whizbangzdecyduje, że chce mieć wszystkie swoje wyjątki w ramach jakiejś wspólnej hierarchii, użycie ApplicationExceptiondo tego celu nie dałoby żadnej przewagi nad używaniem niestandardowej WhizbangExceptionklasy bazowej. Poważniejszy problem w hierarchii wyjątków .net nie dotyczy ApplicationExceptionjednak, ale niepowodzenia rozdzielenia wyjątków na kategorie prawdopodobnie krytyczne dla aplikacji, prawdopodobnie fatalne wątku i związane z problemem lokalnym, a także brak możliwości znaczące „złożone” wyjątki.
supercat
@JoshKodroff: W prawidłowo zaprojektowanej strukturze wyjątków, IMHO, jeśli wyjątek zostanie finallyzgłoszony podczas bloku, podczas gdy inny wyjątek jest w toku, catchbloki w górę stosu wywołań powinny być wyzwalane, jeśli pasują do dowolnego zagnieżdżonego wyjątku, ale pozostawiaj inne wyjątki w toku, aby wyjście catchblok by przejść do innego catchbloku w tym samym trybloku, (jeśli są odpowiednie) i wychodzenia z finallybloku z wyjątkami w toku by przejść do następnej zewnętrznej catchlub finally.
supercat
2
@JoshKodroff Jest jeszcze jedna rzecz, na którą jestem zaskoczony, że nie przyciąga więcej uwagi. Czym tak naprawdę jest „aplikacja”? A co z bibliotekami innych firm ? Ponieważ nie są one częścią środowiska .Net, zgodnie z oryginalnymi wytycznymi powinny dziedziczyć po ApplicationException. Teraz, gdy używasz tej biblioteki w swojej aplikacji, a także tworzysz własne ApplicationExceptions, nie możesz już na tej podstawie odróżniać własnych wyjątków od wyjątków biblioteki. Więc to jest bezużyteczne. Zamiast tego każdy komponent powinien po prostu zdefiniować swój własny typ bazowy wyjątku, tak jak opisuje supercat.
Oskar Berggren
22

W początkowym projekcie, w .NET 1.0, planowano, że sam framework będzie rzucał SystemExceptioni wyprowadzał; podczas gdy aplikacje użytkownika - wyrzucąApplicationException i uzyskiwać.

Ale później, w .NET 2.0, zostało to odrzucone.

W ten sposób pochodzą z Exception.

abatishchev
źródło