Was auch immer sich in den endgültigen Blöcken befindet, wird (fast) immer ausgeführt. Was ist also der Unterschied zwischen dem Einschließen von Code oder dem Nicht-Schließen von Code?
Was auch immer sich in den endgültigen Blöcken befindet, wird (fast) immer ausgeführt. Was ist also der Unterschied zwischen dem Einschließen von Code oder dem Nicht-Schließen von Code?
Antworten:
Der Code in einem finally-Block wird ausgeführt, unabhängig davon, ob eine Ausnahme vorliegt oder nicht. Dies ist sehr praktisch, wenn es um bestimmte Reinigungsfunktionen geht, die Sie immer wie das Schließen von Verbindungen ausführen müssen.
Ich vermute, Ihre Frage ist, warum Sie dies tun sollten:
try
{
doSomething();
}
catch
{
catchSomething();
}
finally
{
alwaysDoThis();
}
Wenn Sie dies tun können:
try
{
doSomething();
}
catch
{
catchSomething();
}
alwaysDoThis();
Die Antwort ist, dass der Code in Ihrer catch-Anweisung häufig entweder eine Ausnahme erneut auslöst oder aus der aktuellen Funktion ausbricht. Mit dem letzteren Code wird "alwaysDoThis ();" Der Aufruf wird nicht ausgeführt, wenn der Code in der catch-Anweisung eine Rückgabe ausgibt oder eine neue Ausnahme auslöst.
Die meisten Vorteile der Verwendung von try-finally wurden bereits hervorgehoben, aber ich dachte, ich würde diesen hinzufügen:
try
{
// Code here that might throw an exception...
if (arbitraryCondition)
{
return true;
}
// Code here that might throw an exception...
}
finally
{
// Code here gets executed regardless of whether "return true;" was called within the try block (i.e. regardless of the value of arbitraryCondition).
}
Dieses Verhalten macht es in verschiedenen Situationen sehr nützlich, insbesondere wenn Sie eine Bereinigung durchführen (Ressourcen entsorgen) müssen, obwohl ein using- Block in diesem Fall häufig besser ist.
Jedes Mal, wenn Sie nicht verwaltete Codeanforderungen wie Stream-Reader, Datenbankanforderungen usw. verwenden. und wenn Sie die Ausnahme abfangen möchten, verwenden Sie try catch finally und schließen Sie den Stream, den Datenleser usw. im finally. Wenn Sie dies nicht tun, wenn die Fehler nicht geschlossen werden, ist dies bei Datenbankanforderungen wirklich schlecht
SqlConnection myConn = new SqlConnection("Connectionstring");
try
{
myConn.Open();
//make na DB Request
}
catch (Exception DBException)
{
//do somehting with exception
}
finally
{
myConn.Close();
myConn.Dispose();
}
Wenn Sie den Fehler nicht abfangen möchten, verwenden Sie
using (SqlConnection myConn = new SqlConnection("Connectionstring"))
{
myConn.Open();
//make na DB Request
myConn.Close();
}
und das Verbindungsobjekt wird automatisch entsorgt, wenn ein Fehler auftritt, Sie den Fehler jedoch nicht erfassen
Denn schließlich wird ausgeführt, auch wenn Sie keine Ausnahme in einem catch-Block behandeln.
Schließlich können Anweisungen auch nach der Rückkehr ausgeführt werden.
private int myfun()
{
int a = 100; //any number
int b = 0;
try
{
a = (5 / b);
return a;
}
catch (Exception ex)
{
Response.Write(ex.Message);
return a;
}
// Response.Write("Statement after return before finally"); -->this will give error "Syntax error, 'try' expected"
finally
{
Response.Write("Statement after return in finally"); // --> This will execute , even after having return code above
}
Response.Write("Statement after return after finally"); // -->Unreachable code
}
finally
, wie in:
try {
// do something risky
} catch (Exception ex) {
// handle an exception
} finally {
// do any required cleanup
}
ist eine garantierte Möglichkeit, Code nach Ihrem try..catch
Block auszuführen , unabhängig davon, ob Ihr try-Block eine Ausnahme ausgelöst hat oder nicht.
Das macht es perfekt für Dinge wie das Freigeben von Ressourcen, Datenbankverbindungen, Dateihandles usw.
Ich werde die Verwendung von schließlich mit einer Dateireader-Ausnahme erklären. Beispiel
try{ StreamReader strReader = new StreamReader(@"C:\Ariven\Project\Data.txt"); Console.WriteLine(strReader.ReadeToEnd()); StreamReader.Close(); } catch (Exception ex) { Console.WriteLine(ex.Message); }
Wenn im obigen Beispiel die Datei mit dem Namen Data.txt fehlt, wird eine Ausnahme ausgelöst und behandelt, aber die aufgerufene AnweisungStreamReader.Close();
wird niemals ausgeführt.
Aus diesem Grund wurden die mit dem Leser verbundenen Ressourcen nie freigegeben.
StreamReader strReader = null; try{ strReader = new StreamReader(@"C:\Ariven\Project\Data.txt"); Console.WriteLine(strReader.ReadeToEnd()); } catch (Exception ex){ Console.WriteLine(ex.Message); } finally{ if (strReader != null){ StreamReader.Close(); } }
Viel Spaß beim Codieren :)
Hinweis: "@" wird verwendet, um eine wörtliche Zeichenfolge zu erstellen , um den Fehler "Nicht erkannte Escape-Sequenz" zu vermeiden. Das @ -Symbol bedeutet, diese Zeichenfolge wörtlich zu lesen und Steuerzeichen nicht anders zu interpretieren.
Angenommen, Sie müssen den Cursor anstelle eines wartenden (Sanduhr-) Cursors auf den Standardzeiger zurücksetzen. Wenn vor dem Setzen des Cursors eine Ausnahme ausgelöst wird und die App nicht sofort abstürzt, kann ein verwirrender Cursor zurückbleiben.
Manchmal möchten Sie keine Ausnahme behandeln (kein catch-Block), aber Sie möchten, dass Bereinigungscode ausgeführt wird.
Beispielsweise:
try
{
// exception (or not)
}
finally
{
// clean up always
}
Der finally-Block ist nützlich, um alle im try-Block zugewiesenen Ressourcen zu bereinigen und Code auszuführen, der ausgeführt werden muss, auch wenn eine Ausnahme vorliegt. Die Steuerung wird immer an den finally-Block übergeben, unabhängig davon, wie der try-Block beendet wird.
Ahh ... ich glaube ich sehe was du sagst! Ich habe eine Sekunde gebraucht ... Sie fragen sich, "warum Sie es in den finally-Block anstatt nach dem finally-Block und vollständig außerhalb des try-catch-finally-Blocks legen".
Dies kann beispielsweise daran liegen, dass Sie die Ausführung anhalten, wenn Sie einen Fehler auslösen, aber dennoch Ressourcen wie geöffnete Dateien, Datenbankverbindungen usw. bereinigen möchten.
Der Kontrollfluss des finally-Blocks erfolgt entweder nach dem Try- oder dem Catch-Block.
[1. First Code]
[2. Try]
[3. Catch]
[4. Finally]
[5. After Code]
mit Ausnahme 1> 2> 3> 4> 5, wenn 3 eine Return-Anweisung 1> 2> 3> 4 hat
ohne Ausnahme 1> 2> 4> 5, wenn 2 eine return-Anweisung 1> 2> 4 hat
Wie in der Dokumentation erwähnt :
Eine übliche Verwendung von catch und finally zusammen besteht darin, Ressourcen in einem try-Block abzurufen und zu verwenden, außergewöhnliche Umstände in einem catch-Block zu behandeln und die Ressourcen im finally-Block freizugeben.
Es lohnt sich auch das Lesen dieser , in der es heißt:
Sobald eine übereinstimmende catch-Klausel gefunden wurde, bereitet sich das System darauf vor, die Kontrolle auf die erste Anweisung der catch-Klausel zu übertragen. Bevor die Ausführung der catch-Klausel beginnt, führt das System zunächst alle finally-Klauseln aus, die mit try-Anweisungen verknüpft waren, die stärker verschachtelt sind als die, die die Ausnahme abgefangen haben.
Es ist also klar, dass Code, der sich in einer finally
Klausel befindet, auch dann ausgeführt wird, wenn eine vorherige catch
Klausel eine return
Anweisung enthält.