Use Case für try-catch-finally mit catch und finally

8

Ich verstehe, wie try-catch funktioniert und wie try-finally funktioniert, aber ich benutze diese (normalerweise) in zwei völlig verschiedenen Szenarien:

  • try-finally (oder using in C # und VB) wird meistens in einem mittelgroßen Codeblock verwendet, der eine Ressource verwendet, die ordnungsgemäß entsorgt werden muss.
  • try-catch wird meistens auch verwendet
    • um eine einzelne Aussage, die auf sehr spezifische Weise scheitern kann oder
    • (als Catch-All) auf einer sehr hohen Ebene der Anwendung, normalerweise direkt unter einer Benutzeroberflächenaktion.

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 zu 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.

    
Heinzi 17.02.2010, 10:15
quelle

10 Antworten

16

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!

    
Filip Ekberg 17.02.2010, 10:23
quelle
12

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.

    
Eric Lippert 17.02.2010 15:11
quelle
10

Beispiel:

%Vor%

Sie können nicht wirklich ein "häufigeres" Beispiel bekommen. Schade, dass manche Leute immer noch vergessen, die enge Verbindung in den Endlich, wo es hingehört, anstatt in den Try Block zu stellen ...: (

    
p.marino 17.02.2010 10:29
quelle
6

Ich oft schreibe Code, der so aussieht:

%Vor%

Vielleicht bist du einfach zu pedantisch ... z. indem man einzelne Aussagen versucht / fängt. (Manchmal ist es notwendig, aber nach meiner Erfahrung müssen Sie normalerweise nicht so feinkörnig sein.)

    
Stephen C 17.02.2010 10:28
quelle
3

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

    
MarkJ 17.02.2010 14:13
quelle
3

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.

    
x4u 17.02.2010 10:46
quelle
1

Ich würde fast immer try-catch-finaly verwenden, wenn Sie in allen Fällen etwas entsorgen müssen, und Sie verwenden den Fall, um den Fehler zu protokollieren und / oder den Benutzer zu informieren.

    
chrissie1 17.02.2010 10:19
quelle
1

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).

    
supercat 28.07.2010 17:35
quelle
0

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.

    
HardCode 17.02.2010 16:11
quelle
-1
  

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?)

    
dart 17.02.2010 10:31
quelle