Was ist der Zweck, bestimmte Exception-Subclasses zu werfen?

8

Warum sollte diese Ausnahme bevorzugt werden?

%Vor%

über dieses allgemeine:

%Vor%

Welchen Vorteil hat dieses Beispiel? Die Nachricht sagt schon alles. Haben Standard-Unterklassen, die von der Basis-Ausnahmeklasse erben, jemals andere Methoden als die Basis? Ich habe keinen Fall gesehen, aber ich muss zugeben, dass ich dazu tendiere, die Basis Exception zu werfen.

    
ChadD 20.10.2010, 17:07
quelle

8 Antworten

20

Der Typ der Ausnahme ermöglicht es den Handlern der Ausnahme, sie zu filtern. Wenn alles, was Sie geworfen haben, Ausnahmen vom Typ Exception wären, wie würden die Handler wissen, welche Ausnahmen zu fangen sind und welche es erlauben sollen, den Call-Stack weiterzugeben?

Zum Beispiel, wenn Sie immer Exception werfen:

%Vor%

Wie weiß der Aufrufer Foo , ob eine Null-Ausnahme aufgetreten ist oder ob Int32.Parse() fehlgeschlagen ist? Es muss den Typ der ausgelösten Ausnahme prüfen (oder einen bösen String-Vergleich durchführen).

Es ist noch besorgniserregender, wenn Sie eine ThreadAbortException oder OutOfMemoryException bekommen, die an Stellen auftreten kann, an denen Sie keine Ausnahme erwarten würden. In diesen Fällen, wenn Ihr Fangcode nur Exception abfängt, können Sie diese (wichtigen) Ausnahmen maskieren und Ihren Programm- (oder System-) Zustand beschädigen.

Der Beispielcode sollte lauten:

%Vor%     
Ron Warholic 20.10.2010, 17:09
quelle
7

Weil Sie mehrere catch-Anweisungen haben und verschiedene Fehler anders behandeln können.

Beispielsweise kann eine DivideByZero-Ausnahme den Benutzer auffordern, einen Eintrag zu korrigieren, während eine FileNotFound-Ausnahme einen Benutzer möglicherweise warnt, dass das Programm nicht fortfahren und das Programm schließen kann.

Es gibt einen ausführlichen Artikel, der diese Frage hier beantwortet: Ссылка

    
David 20.10.2010 17:12
quelle
5

Statt auf der Grundlage des über den Fehlerdatenstrom gesendeten Texts zu filtern, können Sie mehrere Arten von Ausnahmen abfangen. Jeder kann einen sehr spezifischen Weg haben, eine Wiederherstellung durchzuführen. Der Text dient nur dazu, dem Benutzer oder dem Debugger Feedback zu geben, aber das Programm kümmert sich um den Ausnahmetyp. Aus demselben Grund gibt es Polymorphismus für benutzerdefinierte Klassen, es gibt Ausnahmen.

Es ist viel einfacher, mehrere catch-Anweisungen für verschiedene Ausnahmearten einzuschließen, als den Nachrichtentext zu analysieren, um zu verstehen, was zu tun ist, um das Problem richtig zu behandeln.

    
Robolulz 20.10.2010 17:12
quelle
4

Direkt von MSDN - Ausnahmebehandlung :

  

Sie können bestimmte Ausnahmen abfangen, wenn Sie verstehen, warum sie in einem bestimmten Kontext ausgelöst werden.

     

Sie sollten nur die Ausnahmen abfangen, von denen Sie wiederherstellen können. Beispielsweise kann eine FileNotFoundException , die aus dem Versuch resultiert, eine nicht existierende Datei zu öffnen, von einer Anwendung bearbeitet werden, da sie das Problem an den Benutzer kommunizieren und es dem Benutzer ermöglichen kann, einen anderen Dateinamen anzugeben oder die Datei zu erstellen. Eine Anforderung zum Öffnen einer Datei, die ein ExecutionEngineException generiert, sollte nicht behandelt werden, da die zugrunde liegende Ursache der Ausnahme nicht mit einiger Sicherheit bekannt sein kann und die Anwendung nicht sicherstellen kann, dass die Ausführung weiterhin sicher ist.

Übernutzen Sie nicht catch . Wenn Sie eine weitere Ausnahme innerhalb eines catch-Blocks auslösen, wird der Stack-Trace zurückgesetzt und wichtige Debugging-Informationen verloren gehen, wie auch hier von MSDN vorgeschlagen:

  

Fang nicht übermäßig zu verwenden. Ausnahmen sollten häufig erlaubt werden, den Aufrufstapel weiterzuleiten.

     

Das Abfangen von Ausnahmen, die Sie nicht legitim behandeln können, verbirgt kritische Debugging-Informationen.

Am Ende sollte das Abfangen einer Ausnahme dazu dienen, bestimmte Ausnahmen zu behandeln, von denen Sie erwarten, dass sie unter bestimmten häufigen Szenarien auftreten, in denen Sie protokollieren oder ein bestimmtes Verhalten beim Ausnahmebefehl haben möchten, andernfalls einfach throw weg Eric Lippert selbst empfiehlt in seinem Blog (siehe Too much reuse < (Artikel).

%Vor%

Anstelle von:

%Vor%

Schließlich muss ein Exception nicht unbedingt einige Besonderheiten als zusätzliche Eigenschaften oder Methoden oder was auch immer anbieten, es ist der Name, der für sich selbst spricht und Ihnen erlaubt, Ihren Fang nach einer bestimmten Art von Ausnahme zu filtern.

EDIT # 1

Ein weiterer interessanter Link zur Fehlerbehandlung auf Eric Lipperts Blog: Ärgerliche Ausnahmen .

    
Will Marcouiller 20.10.2010 17:51
quelle
3

Die verschiedenen Unterklassen von Exception tragen eine semantische Bedeutung - eine ArgumentNullException zeigt ein anderes Problem an als eines, das eine DivideByZeroException erzeugt, und der Programmierer kann diese Probleme anders behandeln. Darüber hinaus können Unterklassen zusätzliche Eigenschaften oder Methoden definieren, die bei der Diagnose oder Behandlung des Problems helfen können, wenn der Programmierer sie verwendet.

    
Ben 20.10.2010 17:27
quelle
3

Eine Ausnahme wird normalerweise entweder (1) abgefangen, protokolliert und erneut ausgelöst, (2) abgefangen und behandelt oder (3) nicht abgefangen.

Wenn es abgefangen, protokolliert und erneut geworfen wird, könnten wichtige zusätzliche Informationen in einem bestimmten Ausnahmetyp gespeichert werden, der es dem Protokollierungscode ermöglicht, reichhaltigere Informationen zu speichern, sodass der Analyst, der versucht, das Problem zu debuggen verursacht die Ausnahme kann dies effizienter.

Wenn es abgefangen und gehandhabt wird, müssen Sie wissen, wie Sie mit dem Problem umgehen. Wenn eine Ausnahme von einem bestimmten Typ ist, dann ist das ein großer Hinweis für den Entwickler, der den Handler darüber schreibt, ob er mit der Ausnahme umgehen kann oder nicht. Sie sollten nur Ausnahmen behandeln, die Sie erwarten und von denen Sie wissen, wie Sie sie wiederherstellen können.

Wenn es nicht abgefangen wird, wird der Prozess untergehen und wahrscheinlich wird irgendwo ein Absturzspeicherauszug gesendet. Jetzt sind wir zurück in Fall (1).

In allen drei Fällen ist es besser, weniger Informationen zu haben.

    
Eric Lippert 21.10.2010 21:47
quelle
1
%Vor%     
abatishchev 20.10.2010 17:28
quelle
1

In einer gut entworfenen Ausnahmehierarchie ermöglicht das Vorhandensein verschiedener Arten von Ausnahmen Catch-Anweisungen, die unter verschiedenen Umständen unterschiedliche Aktionen ausführen. Idealerweise würde eine Familie von Ausnahmen aus einer Funktion hervorgehen, wenn die bestimmte Aktion nicht abgeschlossen werden konnte, aber Klasseninvarianten, die vor dem Versuch hätten gelten sollen, wahrscheinlich noch immer gelten, mit Ausnahme der durch den Fehlschlag der Aktion implizierten Ausnahme. Die Get-Object-Methode einer Auflistung sollte beispielsweise eine Ausnahme aus dieser Familie auslösen, wenn die Auflistung gültig ist, das angeforderte Objekt jedoch nicht existiert.

Wenn eine Funktion auf eine Weise fehlschlägt, die darauf hinweist, dass Klasseninvarianten beim Aufruf nicht gehalten wurden oder nicht mehr bestehen, nachdem sie zurückgegeben wurde, sollte eine Ausnahme aus einer anderen Familie ausgelöst werden. Beachten Sie, dass es für eine Funktion angemessen sein kann, eine Ausnahme von der ersten Familie abzufangen und als zweite erneut auszuführen, wenn die Ausnahme nur dann eintreten würde, wenn Invarianten verletzt würden. Es kann auch gelegentlich angebracht sein, eine Ausnahme vom zweiten Typ zu fangen und eine der ersten zu werfen, wenn die Ausnahmen von einem Objekt kommen, das niemals verwendet wird, nachdem die Funktion zurückkehrt.

Wenn die Dinge wirklich schlimm sind (z. B. OutOfMemoryException, CpuCatchingFireException usw.), sollte dies eine andere Hierarchie als die ersten beiden sein.

Vorhandene Ausnahmen folgen nicht diesem Muster, aber man könnte es für alle neuen Ausnahmen verwenden, die man erstellt.

    
supercat 20.10.2010 17:45
quelle

Tags und Links