Ich verstehe, wie try-catch funktioniert und wie try-finally funktioniert, aber ich benutze diese (normalerweise) in zwei völlig verschiedenen Szenarien:
using
in C # und VB) wird meistens in einem mittelgroßen Codeblock verwendet, der eine Ressource verwendet, die ordnungsgemäß entsorgt werden muss. Nach meiner Erfahrung sind Fälle, in denen try-catch-finally angebracht wäre, dh wo der Block, in dem ich eine bestimmte Ausnahme abfangen möchte, genau ist Der selbe Block, in dem ich eine verfügbare Ressource verwende, ist extrem selten. Aber die Sprachdesigner von C # , VB und Java scheint dies als sehr häufiges Szenario zu betrachten. Die VB-Designer denken sogar darüber nach, catch using
Vermisse ich etwas? Oder bin ich mit meinem restriktiven Einsatz von try-catch zu pedantisch?
BEARBEITEN: Zur Verdeutlichung: Mein Code sieht normalerweise so aus (die Funktionen wurden aus Gründen der Übersichtlichkeit ausgerollt):
%Vor%scheint nur viel sinnvoller zu sein, als einen der beiden Fänge auf die gleiche Ebene wie schließlich zu setzen, nur um Einrückungen zu vermeiden.
Ein Zitat von MSDN
Eine häufige Verwendung von Fang und schließlich zusammen ist zu erhalten und zu verwenden Ressourcen in einem try-Block, mit denen umzugehen außergewöhnliche Umstände in einem Fang blockieren und die Ressourcen freigeben der endgültige Block.
Um es noch klarer zu machen, denken Sie an den Code, den Sie ausführen möchten, in 99% der Fälle läuft er perfekt, aber irgendwo im Chunk kann ein Fehler auftreten, Sie wissen nicht wo und Erstellte Ressourcen sind teuer.
Um 100% sicher zu sein, dass die Ressourcen entsorgt werden, verwenden Sie den finally-Block. Sie möchten jedoch in 1% der Fälle, in denen der Fehler auftritt, genau bestimmen, weshalb Sie die Anmeldung möglicherweise einrichten möchten der Fangabschnitt.
Das ist ein sehr häufiges Szenario.
Bearbeiten - Ein praktisches Beispiel
Es gibt einige gute Beispiele hier: SQL-Transaktionen mit der SqlTransaction-Klasse . Dies ist nur eine der vielen Möglichkeiten, Try, Catch & amp; Schließlich und es zeigt es sehr gut, auch wenn ein using(var x = new SqlTranscation)
einige Male effizient sein könnte.
Also hier.
%Vor%Hier kommen die interessanteren Teile
%Vor%Stellen wir uns also vor, dass das obige aus irgendeinem Grund fehlschlägt und eine Ausnahme ausgelöst wird
%Vor%Die Transaktion wird zurückgesetzt! Denken Sie daran, dass Änderungen, die Sie an Objekten im try / catch vorgenommen haben, nicht rückgängig gemacht werden, auch nicht, wenn Sie sie in einem using-Objekt verschachteln!
%Vor%Jetzt sind die Ressourcen aufgeräumt!
Keine Antwort auf Ihre Frage, aber eine lustige Tatsache.
Die Microsoft-Implementierung des C # -Compilers kann try-catch-finally tatsächlich nicht verarbeiten. Wenn wir den Code analysieren
%Vor%wir geben tatsächlich vor, dass der Code geschrieben wurde
%Vor%Auf diese Weise muss der Rest des Compilers - der semantische Analysator, der Erreichbarkeitsüberprüfer, der Code-Generator und so weiter - nur mit try-catch und try-finally fertig werden, niemals try-catch-finally. Ein bisschen eine dumme frühe Transformation meiner Meinung nach, aber es funktioniert.
Ich denke, Sie haben vollkommen recht. Aus den Net Framework Design Guidelines , geschrieben von einigen der Besten Architekten bei Microsoft:
NICHT überlagern. Ausnahmen sollten oft erlaubt, sich zu verbreiten Anrufliste.
In gut geschriebenem Code, try-finally [oder Verwendung] ist viel häufiger als Versuch zu fangen. Es scheint anfänglich kontraintuitiv, aber fangen Blöcke werden nicht überraschend benötigt Zahl der Fälle. Andererseits, Du solltest immer überlegen ob try-finally [oder using] könnte nützlich sein für die Säuberung.
Seite 230 Abschnitt 7.2
Es ist nichts falsch daran, try / catch / finally-Blöcke zu verschachteln. Ich benutze das ziemlich oft. I.e. wenn ich eine Ressource verwende, die entsorgt oder geschlossen werden muss, aber ich möchte nur einen einzigen catch-Block um eine größere Code-Einheit, der abgebrochen werden muss, wenn ein Fehler darin auftritt.
%Vor%Dies schließt die Ressource in beiden Fällen so früh wie möglich (Fehler oder nicht), behandelt jedoch alle möglichen Fehler beim Erstellen oder Verwenden der Ressource in einem einzigen catch-Block.
Wie wäre es mit etwas wie:
%Vor%Angenommen, die RollbackFailureException enthält ein "OriginalException" -Feld sowie "InnerException" und akzeptiert Parameter für beide. Man möchte nicht die Tatsache verbergen, dass während des Rollbacks eine Ausnahme aufgetreten ist, aber auch nicht die ursprüngliche Ausnahme, die den Rollback verursacht hat, verlieren (und könnte einen Hinweis geben, warum das Rollback passiert ist).
Eine andere Verwendung wäre, eine Dateizugriffsnummer an einen E-Mail-Anhang zu senden, wenn Sie die Mail-Objekte System.Web.Mail zum Senden von E-Mails verwenden. Ich fand das heraus, als ich einen Crystal Report programmatisch öffnen, auf Diskette speichern, an eine E-Mail anhängen und dann von der Festplatte löschen musste. Eine explizite .Dispose () war in der Endlich erforderlich, um sicherzustellen, dass ich es löschen konnte, insbesondere im Falle einer ausgelösten Ausnahme.
Nach meiner Erfahrung sind Fälle, in denen ein try-catch-finally angemessen wäre, d. h. wo der Block, in dem ich eine bestimmte Ausnahme abfangen möchte, genau der selbe Block ist, in dem ich eine verfügbare Ressource verwende. Die Sprachdesigner von C #, VB und Java halten dies jedoch für ein sehr häufiges Szenario; Die VB-Designer denken sogar darüber nach, ob sie die Verwendung von Catch noch etwas hinzufügen können.
Sie:
%Vor%ich:
%Vor%Gefühl defference?)
Tags und Links language-agnostic java c# vb.net try-catch-finally