Wofür ist ApplicationException in .NET?

172

Um Ausnahmen auszulösen, verwende ich normalerweise integrierte Ausnahmeklassen, z . B. ArgumentNullExceptionund NotSupportedException. Manchmal muss ich jedoch eine benutzerdefinierte Ausnahme verwenden und in diesem Fall schreibe ich:

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

und so weiter. Dann werfe ich und fange diese in meinem Code. Aber heute bin ich auf die ApplicationExceptionKlasse gestoßen - sollte ich das stattdessen verwenden? Wofür ist das?

Es scheint ineffizient zu sein, viele effektiv identische Ausnahmeklassen mit unterschiedlichen Namen zu haben (normalerweise benötige ich keine individuellen Funktionen). Aber ich mag die Idee nicht, ein Generikum zu fangen ApplicationExceptionund zusätzlichen Code verwenden zu müssen, um den Fehler zu bestimmen.

Wo sollte ApplicationExceptionmein Code passen?

James
quelle
35
Tolle Frage, auch +1 für die clever benannten Beispielausnahmen
Cody Gray

Antworten:

100

Nach den Ausführungen in msdn:

Benutzeranwendungen, nicht die Common Language Runtime, lösen benutzerdefinierte Ausnahmen aus, die von der ApplicationException-Klasse abgeleitet sind. Die ApplicationException-Klasse unterscheidet zwischen von Anwendungen definierten Ausnahmen und vom System definierten Ausnahmen.

Wenn Sie eine Anwendung entwerfen, die eigene Ausnahmen erstellen muss, wird empfohlen, benutzerdefinierte Ausnahmen von der Exception-Klasse abzuleiten. Es wurde ursprünglich angenommen, dass benutzerdefinierte Ausnahmen von der ApplicationException-Klasse abgeleitet werden sollten. In der Praxis wurde jedoch kein signifikanter Mehrwert festgestellt. Weitere Informationen finden Sie unter Best Practices für den Umgang mit Ausnahmen.

Leiten Sie sie von ab Exception. Außerdem sehe ich kein Problem beim Erstellen neuer Ausnahmen für Ihre Fälle, solange dies gerechtfertigt ist. Wenn Sie auf einen Fall stoßen, in dem das Framework bereits eine Ausnahme enthält, verwenden Sie diesen, andernfalls rollen Sie Ihre eigene.

Femaref
quelle
9
Es scheint also ApplicationExceptionnutzlos zu sein und gibt es nur wegen der Abwärtskompatibilität?
Beatles1692
In der neuen MSDN-Dokumentation, mindestens 4.7.2, fehlt diese Bemerkung. Danke für das Qutoe: D
Alex
147

Die kurze Antwort lautet: Nirgendwo.

Es ist ein Relikt der Vergangenheit, in dem Microsoft beabsichtigte, dass Entwickler alle ihre benutzerdefinierten Ausnahmen von ApplicationException erben. Kurz darauf änderten sie ihre Meinung und rieten, dass benutzerdefinierte Ausnahmen von der Basisausnahmeklasse abgeleitet werden sollten. Siehe Best Practices für den Umgang mit Ausnahmen in MSDN.

Einer der am weitesten verbreiteten Gründe hierfür ist ein Auszug aus Jeffery Richter in den Framework Design Guidelines :

System.ApplicationException ist eine Klasse, die nicht Teil von .NET Framework sein sollte. Die ursprüngliche Idee war, dass von SystemException abgeleitete Klassen Ausnahmen anzeigen würden, die von der CLR (oder dem System) selbst ausgelöst wurden, während Nicht-CLR-Ausnahmen von ApplicationException abgeleitet würden . Viele Ausnahmeklassen folgten jedoch nicht diesem Muster. Beispielsweise wird TargetInvocationException (die von der CLR ausgelöst wird) von ApplicationException abgeleitet . Daher hat die ApplicationException- Klasse jede Bedeutung verloren. Der Grund für die Ableitung von dieser Basisklasse besteht darin, dass Code weiter oben im Aufrufstapel die Basisklasse abfängt. Es konnten nicht mehr alle Anwendungsausnahmen abgefangen werden.

Da haben Sie es also. Die Zusammenfassung lautet, dass ApplicationException nicht schädlich , sondern nur nutzlos ist .

Schnell Joe Smith
quelle
2
Weiß jemand warum das so ist? Es scheint sinnvoll zu sein, App-Ausnahmen anzuzeigen, aber keine "Programmierer vermasselten" Ausnahmen.
Josh Kodroff
9
Übrigens scheint es aus dieser Erklärung, dass dies an sich kein schlechtes Design ist, sondern dass MSFT die Implementierung vermasselt hat. Liest das noch jemand ähnlich?
Josh Kodroff
8
@JoshKodroff: Ich denke, das Problem ist, dass wenn die Anwendung Whizbangentscheidet, dass sie alle Ausnahmen unter einer gemeinsamen Hierarchie haben möchte, die Verwendung ApplicationExceptionfür diesen Zweck wirklich keinen Vorteil gegenüber der Verwendung einer benutzerdefinierten WhizbangExceptionBasisklasse bietet . Das schwerwiegendere Problem in der Ausnahmehierarchie von .net liegt jedoch nicht darin ApplicationException, sondern darin, dass Ausnahmen nicht in Kategorien unterteilt werden können, die wahrscheinlich die Anwendung betreffen, wahrscheinlich den Thread beeinträchtigen und lokale Probleme betreffen, zusammen mit der Unfähigkeit, diese zu haben sinnvolle "zusammengesetzte" Ausnahmen.
Supercat
@JoshKodroff: Wenn in einem ordnungsgemäß gestalteten Ausnahmeframework IMHO, wenn eine Ausnahme während des finallyBlockierens ausgelöst wird , während eine andere Ausnahme ansteht, catchBlöcke weiter oben im Aufrufstapel ausgelöst werden sollten, wenn sie mit einer verschachtelten Ausnahme übereinstimmen , andere Ausnahmen jedoch anstehen, damit sie beendet werden Ein catchBlock würde zu einem anderen catchBlock innerhalb desselben tryBlocks übergehen (falls vorhanden), und das Verlassen eines finallyBlocks mit ausstehenden Ausnahmen würde zum nächsten äußeren catchoder springen finally.
Supercat
2
@JoshKodroff Es gibt noch eine Sache, die mich überrascht, nicht mehr Aufmerksamkeit zu bekommen. Was ist eigentlich eine "Anwendung"? Was ist mit Bibliotheken von Drittanbietern ? Da diese nicht Teil des .Net-Frameworks sind, sollten sie nach den ursprünglichen Richtlinien von ApplicationException erben. Wenn Sie diese Bibliothek in Ihrer Anwendung verwenden und auch eigene ApplicationExceptions erstellen, können Sie Ihre eigenen Ausnahmen nicht mehr von der darauf basierenden Ausnahme der Bibliothek unterscheiden. Es ist also nutzlos. Stattdessen sollte jede Komponente einfach ihren eigenen Ausnahmebasis-Typ definieren, wie von Supercat beschrieben.
Oskar Berggren
22

Im ursprünglichen Entwurf in .NET 1.0 war geplant, dass das Framework selbst ausgelöst SystemExceptionund abgeleitet wird. während Benutzeranwendungen - werfen ApplicationExceptionund abgeleitet.

Aber später in .NET 2.0 wurde das gelöscht.

Also ableiten von Exception.

abatishchev
quelle