Frage

Ich habe gesehen, wie Leute sagen, dass es schlechte Form ist Fang ohne Argumente zu verwenden, insbesondere wenn das Catch nichts tut:

StreamReader reader=new  StreamReader("myfile.txt");
try
{
  int i = 5 / 0;
}
catch   // No args, so it will catch any exception
{}
reader.Close();

Dies ist jedoch als gute Form:

StreamReader reader=new  StreamReader("myfile.txt");
try
{
  int i = 5 / 0;
}
finally   // Will execute despite any exception
{
  reader.Close();
}

Soweit ich das beurteilen kann, ist der einzige Unterschied zwischen dem Bereinigungscode in einem finally-Block setzen und Bereinigungscode nach den try..catch Blöcken setzen, wenn Sie return-Anweisungen in Ihrem Try-Block (in diesem Fall haben, der Bereinigungscode in endlich laufen, aber Code nach dem try..catch nicht).

Ansonsten was schließlich so besonders?

War es hilfreich?

Lösung

Der große Unterschied ist, dass try...catch die Ausnahme schlucken wird, versteckt sich die Tatsache, dass ein Fehler aufgetreten ist. try..finally Ihren Bereinigungscode ausführen und dann wird die Ausnahme weitermachen, von etwas behandelt werden, der weiß, was damit zu tun.

Andere Tipps

„Schließlich“ ist eine Aussage über „Etwas, das man muss immer darauf geachtet werden Programmzustand auszukommen, ist gesund“. Als solches ist es immer gut in Form, einen zu haben, wenn eine Möglichkeit gibt es, dass Ausnahmen den Programmzustand abwerfen können. Der Compiler geht auch auf große Längen, um sicherzustellen, dass Ihr Schließlich Code ausgeführt wird.

„Catch“ ist eine Aussage von „ich von dieser Ausnahme erholen kann“. Sie sollten nur von Ausnahmen wiederherstellen können Sie wirklich korrigieren -. Fangen ohne Argumente sagt: „Hey, ich von etwas erholen kann“, was fast immer falsch ist

Wenn es möglich wäre, von jeder Ausnahme zu erholen, dann wäre es wirklich eine semantische Haarspalterei sein, zu wissen, was Sie Ihre Absicht sind erklärt wird. Allerdings ist es nicht, und mit ziemlicher Sicherheit Rahmen über Ihr besser ausgestattet sein werden bestimmte Ausnahmen zu behandeln. Als solche nutzen schließlich, erhalten Sie Ihren Bereinigungscode läuft kostenlos, aber immer noch mehr Wissen Handler mit dem Thema beschäftigen lassen.

Weil, wenn die eine einzige Zeile eine Ausnahme auslöst, Sie würden es nicht wissen.

Mit dem ersten Code-Block, wird die Ausnahme einfach sein absorbierte , das Programm weiter, auch auszuführen, wenn der Zustand des Programms könnte falsch sein.

Mit dem zweiten Block wird die Ausnahme sein geworfen und sprudelt und die reader.Close() weiterhin gewährleistet ist auszuführen.

Wenn eine Ausnahme nicht erwartet wird, dann einen try..catch Block nicht nur so setzt, wird es schwierig sein, später zu debuggen, wenn das Programm in einen schlechten Zustand ist und Sie haben keine Ahnung, warum.

Schließlich ausgeführt wird, egal was passiert. Also, wenn Ihr try-Block erfolgreich war es wird ausgeführt, wenn Ihr try-Block ausfällt, es wird dann den catch-Block ausgeführt werden, und dann wird die finally-Block.

Außerdem ist es besser, versuchen das folgende Konstrukt zu verwenden:

using (StreamReader reader=new  StreamReader("myfile.txt"))
{
}

Wie die Anweisung using automatisch in einem Try / finally gewickelt wird und der Strom automatisch geschlossen. (Sie müssen einen Versuch setzen / um die Anweisung using fangen, wenn Sie die Ausnahme tatsächlich fangen).

Während die folgenden zwei Codeblöcke äquivalent sind, sind sie nicht gleich.

try
{
  int i = 1/0; 
}
catch
{
  reader.Close();
  throw;
}

try
{
  int i = 1/0;
}
finally
{
  reader.Close();
}
  1. ‚endlich‘ ist Absicht offenbarenden Code. Sie erklären den Compiler und andere Programmierer, dass dieser Code, egal was ausgeführt werden muss.
  2. , wenn Sie mehrere catch-Blöcke haben, und Sie Bereinigungscode haben, müssen Sie schließlich. Ohne schließlich, würden Sie Ihren Bereinigungscode in jedem catch-Block zu duplizieren. (DRY-Prinzip)

schließlich Blöcke speziell sind. Die CLR erkennt und behandelt Code withing ein schließlich getrennt von Catch-Blöcke sperren, und die CLR geht auf große Längen zu gewährleisten, dass ein finally-Block wird immer ausgeführt werden. Es ist nicht nur syntaktischer Zucker vom Compiler.

ich mit einigen, was scheint hier den Konsens zu sein - ein leerer ‚Fang‘ ist schlecht, weil es Masken was auch immer Ausnahme im try-Block aufgetreten sind

.

Auch von einem Ablesbarkeit Standpunkt, wenn ich einen ‚versucht‘ Block zu sehen gehe ich davon aus wird es eine entsprechende ‚catch‘ Anweisung sein. Wenn Sie nur in dem ‚endlich‘ Block de-allocate a ‚versuchen‘, um sicherzustellen, Ressourcen verwenden, können Sie die Anweisung 'mit' statt:

using (StreamReader reader = new StreamReader('myfile.txt'))
{
    // do stuff here
} // reader.dispose() is called automatically

Sie können die ‚mit‘ Aussage mit jedem Objekt, das IDisposable implementiert. Des Objekts dispose () -Methode automatisch am Ende des Blocks aufgerufen wird.

Der try..finally Block wird nach wie vor alle Ausnahmen werfen, die angehoben werden. Alle finally tut, ist sicherzustellen, dass der Code Bereinigung ausgeführt wird, bevor die Ausnahme ausgelöst wird.

Die try..catch mit einem leeren Fang verbraucht vollständig jede Ausnahme und hinwegtäuschen, dass es passiert ist. Der Leser wird geschlossen, aber es ist nicht abzusehen, ob die richtige Sache passiert ist. Was passiert, wenn Ihre Absicht zu schreiben, war i in die Datei? In diesem Fall werden Sie es nicht zu, dass ein Teil des Codes und myfile.txt leer. Sie alle nachgeordneten Methoden, um dies richtig behandeln? Wenn Sie die leere Datei sehen, werden Sie in der Lage richtig zu erraten, dass es leer ist, weil eine Ausnahme ausgelöst wurde? Besser die Ausnahme zu werfen und ließ wissen, dass Sie etwas falsch machen.

Ein weiterer Grund ist die try..catch wie dies geschehen ist völlig falsch. Was sagen Sie, indem Sie diese ist: „Egal was passiert, ich kann damit umgehen.“ Was ist StackOverflowException, können Sie danach aufzuräumen? Was ist OutOfMemoryException? In der Regel sollten Sie nur Ausnahmen behandeln, die Sie erwarten und wissen, wie zu behandeln.

Verwenden Try..Catch..Finally, wenn Ihre Methode weiß, wie die Ausnahme lokal zu behandeln. Die Ausnahme tritt in Versuchen, Handled in Fang und danach aufzuräumen in Endlich fertig.

Im Fall, wenn Ihre Methode nicht weiß, wie die Ausnahme zu behandeln, muss aber eine Bereinigung, sobald es die Verwendung Try..Finally

aufgetreten ist

Dies wird durch die Ausnahme von den Aufrufen von Methoden propagiert wird und behandelt, wenn es irgendwelche geeigneten Fangmeldungen in der anruf sind Methoden an gibt es keine Ausnahmehandler in der aktuellen Methode oder eine der anrufenden Methoden dann die Anwendung abstürzt.

Mit dem Try..Finally sichergestellt ist, dass die lokalen aufzuräumen erfolgten vor der Ausnahme an den anrufenden Methoden zu verbreiten.

Wenn Sie nicht wissen, welcher Ausnahmetyp zu fangen oder, was damit zu tun, gibt es keinen Punkt eine catch-Anweisung zu haben. Sie sollten es einfach gehen für einen höheren-up Anrufer, die mehr Informationen über die Situation haben zu wissen, was zu tun ist.

Sie sollten noch eine endlich Aussage drin haben, falls es eine Ausnahme, so dass Sie Ressourcen bereinigen können, bevor diese Ausnahme vom Anrufer ausgelöst wird.

Von einer Ablesbarkeit Perspektive, es ist mehr explizit zukünftige Code-Leser sagen, „dieses Zeug hier ist wichtig, es egal getan werden muss, was passiert.“ Das ist gut.

Auch leere catch-Anweisungen sind in der Regel einen gewissen „Geruch“, um sie zu haben. Sie könnten ein Zeichen dafür sein, dass Entwickler nicht durch die verschiedenen Ausnahmen denken, die auftreten können und wie sie zu behandeln.

ist schließlich optional - es gibt keinen Grund, ein „Endlich“ Block zu haben, wenn es keine Mittel gibt, um aufzuräumen

.

Entnommen: hier

Raising und fangen Ausnahmen sollten nicht routinemäßig als Teil der erfolgreichen Durchführung eines Verfahrens auftreten. Wenn Klassenbibliotheken zu entwickeln, Client-Code muss die Möglichkeit für einen Fehlerzustand zu testen gegeben werden, bevor eine Operation Unternehmen, die in einer Ausnahme angehoben führen können. Zum Beispiel bietet System.IO.FileStream eine CanRead Eigenschaft, die vor dem Aufruf die Read-Methode überprüft werden kann, eine mögliche Ausnahme zu verhindern angehoben wird, wie im folgenden Codeausschnitt dargestellt:

Dim str als Strom = GetStream () Wenn (str.CanRead) Then   ‚Code lesen Strom End If

Die Entscheidung, ob der Zustand eines Objekts zu überprüfen, bevor eine bestimmte Methode zum Aufruf, die eine Ausnahme ist abhängig von der erwarteten Zustand des Objekts zu erhöhen. Wenn ein Filestream-Objekt wird einen Dateipfad erstellt, die existieren sollten und einen Konstruktor, der eine Datei im Lesemodus zurückkehren soll, die CanRead Eigenschaft Überprüfung ist nicht erforderlich; die Unfähigkeit, die Filestream wäre ein Verstoß gegen das erwartete Verhalten der Methodenaufrufe gemacht, und eine Ausnahme sollte angehoben werden, zu lesen. Wenn dagegen ein Verfahren, wie Zurückgeben eines Filestream-Referenz dokumentiert ist, die nicht lesbar sein oder kann die CanRead Eigenschaft überprüfen, bevor Sie Daten empfiehlt sich zu lesen.

, um die Auswirkungen auf die Leistung zu zeigen, dass eine „laufen, bis Ausnahme“ Codierung Technik kann dazu führen, die Leistung eines Darstellers, der eine InvalidCastException aus, wenn die Umwandlung fehlschlägt, ist mit dem C # als Operator verglichen, die NULL-Werte, wenn eine Besetzung zurück schlägt fehl. Die Leistung der beiden Verfahren ist identisch für den Fall, in dem der gegossene gültig ist (siehe Test 8,05), aber für den Fall, daß das gegossene ungültig ist, und unter Verwendung einer Guss eine Ausnahme verursacht, unter Verwendung einer Guss ist 600-mal langsamer als die Verwendung von als Operator (siehe Test 8,06). Die Hochleistungs Auswirkungen der Ausnahme werfende Technik beinhaltet die Kosten des Zuweisens, werfen, und fangen die Ausnahme und die Kosten für die nachfolgende Speicherbereinigungs des Objekts Ausnahme, das heißt die momentane Auswirkung Auslösen einer Ausnahme ist das nicht hoch. Da immer mehr Ausnahmen geworfen werden, häufig Garbage Collection ein Problem wird, so dass die Gesamtwirkung der häufigen Verwendung einer exception- Wurftechnik Codierung wird ähnlich seine 8,05 zu testen.

Es ist eine schlechte Praxis eine catch-Klausel hinzufügen nur die Ausnahme erneut auslösen.

Wenn Sie lesen C # für Programmierer Sie werden verstehen, dass der finally-Block wurde Design eine Anwendung und verhindert Speicherverlust.

optimieren
  

Die CLR nicht vollständig Lecks beseitigen ... Speicherlecks auftreten können, wenn das Programm versehentlich Verweise auf unerwünschte Objekte halten

Zum Beispiel, wenn Sie eine Datei oder Datenbank-Verbindung öffnen, wird Ihre Maschine Speicher zuweisen, dass die Transaktion gerecht zu werden, und dass der Speicher nicht gehalten werden, es sei denn, die entsorgt oder Schließbefehl ausgeführt wurde. aber wenn während der Transaktion wurde ein Fehler aufgetreten ist, wird das Verfahren beendet Befehl nicht, wenn es innerhalb des try.. finally.. Block war.

catch unterschied sich von finally in dem Sinne, dass, Entwurf, den Sie fangen war viel zu geben, zu handhaben / verwalten oder den Fehler es selbst zu interpretieren. Betrachten Sie es als Person, die Ihnen sagt, „Hey, ich fing einige Bösewichte, was Sie wollen, dass sie tun?“ um sicherzustellen, wurde während finally gestaltet, dass wurde Ihre Ressourcen richtig platziert. Denken Sie daran, von jemandem, ob oder nicht es gibt einige Bösewichte er dafür sorgen, dass Ihr Eigentum noch sicher war.

Und Sie sollten die beiden arbeiten zusammen für eine gute ermöglichen.

Beispiel:

try
{
  StreamReader reader=new  StreamReader("myfile.txt");
  //do other stuff
}
catch(Exception ex){
 // Create log, or show notification
 generic.Createlog("Error", ex.message);
}
finally   // Will execute despite any exception
{
  reader.Close();
}

Mit schließlich können Sie Ressourcen aufzuräumen, auch wenn Ihre catch-Anweisung die Ausnahme bis zum rufenden Programm wirft. Mit Ihrem Beispiel der leere catch-Anweisung enthält, gibt es kaum einen Unterschied. Wenn jedoch in Ihrem Fang, Sie einige Berechnungen durchführen und die Fehler werfen oder gar nicht einfach selbst einen Haken hat überhaupt, die schließlich noch erhält Lauf.

Gut für ein, es ist eine schlechte Praxis Ausnahmen fangen Sie nicht die Mühe zu behandeln. Schauen Sie sich Kapitel 5 über .Net Leistung von Verbesserung. NET Application Performance und Skalierbarkeit . Seite beachten, sollten Sie wahrscheinlich den Strom innerhalb des Try-Block, auf diese Weise werden geladen haben, können Sie die einschlägige Ausnahme fangen, wenn es fehlschlägt. Erstellen der Strom außerhalb des Try-Block besiegt seinen Zweck erfüllt.

In der wahrscheinlich viele Gründe, Ausnahmen sind sehr langsam auszuführen. Sie können Ihre Laufzeiten leicht lahmlegen, wenn dies viel passiert.

Das Problem mit try / catch-Blöcken, die alle Ausnahmen zu fangen ist, dass Ihr Programm wird nun in einem unbestimmten Zustand ist, wenn eine unbekannte Ausnahme auftritt. Das geht völlig gegen die schnelle Regel scheitern - Sie wollen nicht Ihr Programm fortzusetzen, wenn eine Ausnahme auftritt. Die obige try / catch würde sogar OutOfMemoryExceptions fangen, aber das ist auf jeden Fall ein Zustand, der Ihr Programm nicht in ausführen.

Versuchen / finally Blöcke können Sie Code auszuführen aufzuräumen, während immer noch schnell scheitern. Für die meisten Umstände, dass Sie nur wollen alle Ausnahmen auf globaler Ebene fangen, so dass Sie sie anmelden können, und dann verlassen werden.

Der effektive Unterschied zwischen Ihren Beispielen ist vernachlässigbar, solange keine Ausnahmen geworfen werden.

Wenn jedoch eine Ausnahme ausgelöst wird, während in dem ‚versuchen‘ -Klausel, das erste Beispiel es vollständig schlucken. Das zweite Beispiel wird die Ausnahme zum nächsten Schritt auf den Call-Stack erhöhen, so dass der Unterschied in den genannten Beispielen ist, dass man verschleiert vollständig alle Ausnahmen (erstes Beispiel), und das andere (zweite Beispiel) behält Ausnahmeinformationen für eine spätere mögliche Handhabung während nach wie vor Ausführen des Inhalts in der ‚endlich‘ -Klausel.

Wenn Sie zum Beispiel Code setzen waren in dem ‚catch‘ -Klausel des ersten Beispiels, das eine Ausnahme ausgelöst hat (entweder derjenige, der ursprünglich erhoben wurde, oder ein neues Geschäft), würde der Leser Bereinigungscode nie ausgeführt. Schließlich führt unabhängig von dem, was in dem 'catch' -Klausel passiert.

Der Hauptunterschied zwischen ‚fängt‘ So, und ‚endlich‘ ist, dass der Inhalt des ‚endlich‘ Blockes (mit einigen wenigen Ausnahmen) in Betracht gezogen werden kann garantiert auszuführen, auch in der Gesicht einer unerwarteten Ausnahme, während jeder Code eine "catch-Klausel folgende (aber außerhalb eines‚endlich‘-Klausel) nicht tragen, eine solche Garantie.

übrigens, Stream und Stream beiden implementieren IDisposable, und können in einem ‚mit‘ Block gewickelt werden. ‚Mit‘ Blöcke sind die semantische Äquivalent try / finally (kein ‚fangen‘), so dass Ihr Beispiel mehr lapidar ausgedrückt werden:

using (StreamReader reader = new  StreamReader("myfile.txt"))
{
  int i = 5 / 0;
}

... die von der Stream Instanz wird geschlossen und entsorgen, wenn sie aus dem Geltungsbereich. Hoffe, das hilft.

try {...} catch {} ist nicht immer schlecht. Es ist nicht ein gemeinsames Muster, aber ich neigen dazu, es zu benutzen, wenn ich zum Herunterfahren Ressourcen benötigen, egal was, wie zu schließen ein (möglicherweise) offene Steckdosen am Ende eines Fadens.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top