Frage

Abgesehen von der Syntax, was ist der Unterschied zwischen

try {
}
catch() {
}
finally {
    x = 3;
}

Und

try {
}
catch() {
}

x = 3;

bearbeiten:in .NET 2.0?


Also

try {
    throw something maybe
    x = 3
}
catch (...) {
    x = 3
}

ist verhaltensmäßig gleichwertig?

War es hilfreich?

Lösung

Hängt von der Sprache ab, da es geringfügige semantische Unterschiede geben kann, aber die Idee ist, dass es (fast) immer ausgeführt wird, selbst wenn der Code im Try-Block eine Ausnahme ausgelöst hat.

Wenn im zweiten Beispiel der Code im Catch-Block zurückkehrt oder beendet wird, wird x = 3 nicht ausgeführt.Im ersten Fall wird es so sein.

In der .NET-Plattform kommt es in manchen Fällen dazu, dass der „finally“-Block nicht ausgeführt wird:Sicherheitsausnahmen, Thread-Suspendierungen, Herunterfahren des Computers :) usw.

Andere Tipps

Nun, zum einen wird, wenn Sie innerhalb Ihres try-Blocks RETURN ausführen, „finally“ immer noch ausgeführt, der unter dem try-catch-finally-Block aufgeführte Code jedoch nicht.

In Java:

„Finally“ wird immer aufgerufen, unabhängig davon, ob die Ausnahme in „catch()“ richtig abgefangen wurde oder ob es überhaupt einen „Catch“ gibt.

Versuchen Sie es zu fangen Endlich ist ein ziemlich wichtiges Konstrukt.Sie können sicher sein, dass der Code im „finally“-Block auch dann ausgeführt wird, wenn eine Ausnahme ausgelöst wird.Im Umgang mit externen Ressourcen ist es sehr wichtig, diese freizugeben.Die Müllabfuhr übernimmt das nicht für Sie.Letztendlich hättest du es nicht tun sollen zurückkehren Anweisungen ausführen oder Ausnahmen auslösen.Das ist möglich, aber es ist eine schlechte Praxis und kann zu unvorhersehbaren Ergebnissen führen.

Wenn Sie dieses Beispiel ausprobieren:

try {
  return 0;
} finally {
  return 2;
}

Das Ergebnis wird 2 sein :)

Vergleich mit anderen Sprachen: Rückkehr von endlich

Es gibt mehrere Dinge, die einen „finally“-Block nützlich machen:

  1. Wenn Sie von den Try- oder Catch-Blöcken zurückkehren, wird der Final-Block immer noch ausgeführt, unmittelbar bevor die Kontrolle an die aufrufende Funktion zurückgegeben wird
  2. Wenn im Catch-Block eine Ausnahme auftritt oder im Try-Block ein nicht abgefangener Ausnahmetyp auftritt, wird der Code im Final-Block weiterhin ausgeführt.

Diese eignen sich hervorragend zum Schließen von Dateihandles oder Sockets.

Für den Fall, dass Try und Catch leer sind, gibt es keinen Unterschied.Andernfalls können Sie sicher sein, dass die endgültige Ausführung erfolgt.

Wenn Sie beispielsweise eine neue Ausnahme in Ihrem Catch-Block auslösen (Rethrow), wird die Zuweisung nur dann ausgeführt, wenn sie im Final-Block steht.

Normalerweise wird ein „finally“ verwendet, um nach sich selbst aufzuräumen (DB-Verbindungen, Dateihandles usw. schließen).

Sie sollten niemals Kontrollanweisungen (return, break, continue) in einem Final verwenden, da dies ein Wartungsalptraum sein kann und daher als schlechte Praxis gilt

Der „finally“-Block wird immer aufgerufen (naja, nicht wirklich). stets ...), auch wenn eine Ausnahme ausgelöst wird oder eine Return-Anweisung erreicht wird (obwohl dies sprachabhängig sein kann).Es ist eine Möglichkeit zum Aufräumen, von der Sie wissen, dass sie immer aufgerufen wird.

@iAn und @mats:

Ich würde in der Regel nichts in „final {}“ „abreißen“, was innerhalb des „try {}“ „eingerichtet“ wurde.Es wäre besser, die Stream-Erstellung außerhalb von try {} durchzuführen.Wenn Sie eine Ausnahme bei der Stream-Erstellung behandeln müssen, kann dies in einem größeren Umfang erfolgen.

StreamReader stream = new StreamReader("foo.bar");  
try {
    mySendSomethingToStream(stream);
}
catch(noSomethingToSendException e) {
    //Swallow this    
    logger.error(e.getMessage());
}
catch(anotherTypeOfException e) {
    //More serious, throw this one back
    throw(e);
}
finally {
    stream.close();  
}

So können Sie alle offenen Verbindungen usw. bereinigen.im Try-Block initialisiert.Wenn Sie eine Verbindung geöffnet haben und dann eine Ausnahme aufgetreten ist, wurde diese Ausnahme nicht ordnungsgemäß geschlossen.Für diese Art von Szenario ist der „finally“-Block gedacht.

Der „final“-Block soll unabhängig davon ausgeführt werden, ob Sie die Ausnahme abgefangen haben oder nicht.Sehen Try/Catch/Endlich Beispiel

@Ed, denken Sie vielleicht an so etwas wie a catch(...) das eine nicht spezifizierte Ausnahme in C++ abfängt.

Aber finally ist Code, der ausgeführt wird, egal was im passiert catch Blöcke.

Microsoft bietet eine Hilfeseite an try-finally für C#

Der „finally“-Block befindet sich im gleichen Gültigkeitsbereich wie „try/catch“, sodass Sie Zugriff auf alle darin definierten Variablen haben.

Stellen Sie sich vor, Sie haben einen Dateihandler. Dies ist der Unterschied in der Schreibweise.

try
{
   StreamReader stream = new StreamReader("foo.bar");
   stream.write("foo");
}
catch(Exception e) { } // ignore for now
finally
{
   stream.close();
}

im Vergleich zu

StreamReader stream = null;
try
{
    stream = new StreamReader("foo.bar");
    stream.write("foo");
} catch(Exception e) {} // ignore

if (stream != null)
    stream.close();

Denken Sie jedoch daran, dass es nicht garantiert ist, dass alles, was sich darin befindet, funktioniert.Stellen Sie sich vor, Sie erhalten ein Abbruchsignal, Windows stürzt ab oder der Strom ist ausgefallen.Es ist schlecht, sich bei geschäftskritischem Code auf „finally“ zu verlassen.

Jeder Code in „final“ wird auch im Falle einer nicht behandelten Ausnahme ausgeführt.Normalerweise wird der Final-Code verwendet, um lokale Deklarationen von nicht verwaltetem Code mithilfe von .dispose() zu bereinigen.

Schließlich ermöglichen Blöcke es Ihnen als Entwickler, selbst aufzuräumen, unabhängig davon, ob bei den Aktionen des vorangehenden Codes im try{}-Block Fehler aufgetreten sind, und andere haben darauf hingewiesen, dass dies hauptsächlich unter das Dach der Ressourcenfreigabe – des Schließens – fällt Zeiger/Sockets/Ergebnismengen, Rückgabe von Verbindungen zu einem Pool usw.

@mats hat völlig recht, dass es immer zu „harten“ Fehlern kommen kann – schließlich sollten Blöcke keinen geschäftskritischen Code enthalten, der immer transaktional innerhalb des Versuchs erfolgen sollte{}

@mats nochmal – Das wirklich Schöne ist, dass Sie damit Ausnahmen aus Ihren eigenen Methoden zurückwerfen können und trotzdem garantieren, dass Sie aufräumen:

try
{
StreamReader stream = new StreamReader("foo.bar");
mySendSomethingToStream(stream);
}
catch(noSomethingToSendException e) {
    //Swallow this    
    logger.error(e.getMessage());
}
catch(anotherTypeOfException e) {
    //More serious, throw this one back
    throw(e);
}
finally
{
stream.close();
}

Wir können also viele Arten von Ausnahmen abfangen und sie unterschiedlich verarbeiten (die erste ermöglicht die Ausführung für alles, was über try{} hinausgeht, die zweite gibt effektiv zurück), aber immer sauber und ordentlich aufräumen.

In Java verwenden Sie es für alles, was Sie ausführen möchten, unabhängig davon, ob Sie ein „Return“ verwendet haben, nur den Try-Block durchlaufen haben oder eine Ausnahme abgefangen wurde.

Zum Beispiel das Schließen einer Datenbanksitzung oder einer JMS-Verbindung oder das Freigeben einer Betriebssystemressource.

Ich vermute, dass es in .NET ähnlich ist?

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