Wird Code-Anweisung Feuer in einem Schließlich, wenn ich einen Wert in einem Try-Block zurückgeben?

StackOverflow https://stackoverflow.com/questions/345091

Frage

Ich bin der Überprüfung einen Code für einen Freund und sagen, dass er innerhalb eines Try-finally-Block eine return-Anweisung wurde mit. Ist der Code im finally Abschnitt noch feuern, obwohl der Rest des Try-Blockes nicht?

Beispiel:

public bool someMethod()
{
  try
  {
    return true;
    throw new Exception("test"); // doesn't seem to get executed
  }
  finally
  {
    //code in question
  }
}
War es hilfreich?

Lösung

Einfache Antwort: Ja.

Andere Tipps

Normalerweise ja. Der finally Abschnitt ist garantiert auszuführen, was mit Ausnahmen oder return-Anweisung geschieht. Eine Ausnahme von dieser Regel ist eine asynchrone Ausnahme auf dem Thread passiert (OutOfMemoryException, StackOverflowException).

Um mehr über Asynchron-Ausnahmen und zuverlässigen Code in diesen Situationen zu erfahren, lesen Sie gezwungen Ausführung Regionen .

Hier ist ein kleiner Test:

class Class1
{
    [STAThread]
    static void Main(string[] args)
    {
        Console.WriteLine("before");
        Console.WriteLine(test());
        Console.WriteLine("after");
    }

    static string test()
    {
        try
        {
            return "return";
        }
        finally
        {
            Console.WriteLine("finally");
        }
    }
}

Das Ergebnis ist:

before
finally
return
after

von MSDN Zitiert

  

schließlich wird ein Anweisungsblock des Codes zu gewährleisten, führt unabhängig davon, wie die vorhergehende versuchen Block ist verlassen .

Generell ja, wird die schließlich ausgeführt werden.

Für die folgenden drei Szenarien, die schließlich werden immer laufen:

  1. Keine Ausnahmen auftreten
  2. Synchrone Ausnahmen (Ausnahmen, die im normalen Programmablauf auftreten).
    Dazu gehört CLS-kompatibel Ausnahmen, die von System.Exception und Nicht-CLS-kompatibel Ausnahmen ableiten, die von System.Exception nicht ableiten. Nicht-CLS-kompatibel Ausnahmen werden automatisch von der RuntimeWrappedException gewickelt. C # kann nicht CLS Beschwerde Ausnahmen nicht werfen, aber Sprachen wie C ++ kann. C # könnte in Code Aufruf in einer Sprache geschrieben, die nicht CLS-kompatibel Ausnahmen auslösen können.
  3. Asynchronous Threadabort
    Ab .NET 2.0 wird eine Threadabort nicht mehr verhindert eine schließlich vom Laufen. Threadabort wird nun vor oder nach der schließlich gehievt. Das wird schließlich immer läuft und wird nicht durch einen Faden Abbruch unterbrochen werden, so lange der Versuch tatsächlich eingegeben wurde, bevor der Thread Abort aufgetreten.

Das folgende Szenario wird das schließlich nicht ausgeführt:

Asynchronous Stackoverflow.
Wie von .NET 2.0 ein Stapelüberlauf bewirkt, dass der Prozess beendet. Das wird schließlich nicht ausgeführt werden, es sei denn, eine weitere Einschränkung die schließlich eine CER (Constrained Execution Region) zu machen angewandt wird. CERs sollte nicht im Allgemeinen Benutzercode verwendet werden. Sie sollten nur verwendet werden, wo es wichtig ist, dass Bereinigungscode immer laufen - schließlich der Prozess heruntergefahren wird auf Stack-Überlauf sowieso und alle verwalteten Objekte werden daher aufgeräumte werden standardmäßig aktiviert. Somit sollte der einzige Ort, ein CER relevant ist für Ressourcen, die außerhalb des Prozesses zugeordnet sind, zum Beispiel, nicht verwalteten Griffe.

Normalerweise nicht verwalteten Code wird von einigen verwalteten Klasse eingewickelt, bevor sie durch Benutzercode verbraucht wird. Die verwaltete Wrapper-Klasse wird in der Regel der Verwendung eines Safehandle macht den nicht verwalteten Griff zu wickeln. Der Safehandle implementiert eine kritische Finalizerthread und eine Release-Methode, die in einem CER ausgeführt wird, um die Ausführung des Clean-up-Code zu gewährleisten. Aus diesem Grund sollten Sie nicht CERs sehen Benutzercode übersät durchgeführt.

So die Tatsache, dass die schließlich nicht auf Stackoverflow laufen sollte keine Auswirkung auf Benutzer-Code haben, da der Prozess ohnehin beendet wird. Wenn Sie einige Rand Fall, wo Sie reinigen-up Sie müssen einige nicht verwaltete Ressource, außerhalb eines Safehandle oder CriticalFinalizerObject, dann eine CER verwenden wie folgt; aber bitte beachten Sie, das ist eine schlechte Praxis -. das nicht verwaltete Konzept sollte zu einer verwalteten Klasse (n) und entsprechende Safehandle (n) nach Design abstrahiert werden

z. B.

// No code can appear after this line, before the try
RuntimeHelpers.PrepareConstrainedRegions();
try
{ 
    // This is *NOT* a CER
}
finally
{
    // This is a CER; guaranteed to run, if the try was entered, 
    // even if a StackOverflowException occurs.
}

Es ist eine sehr wichtige Ausnahme hiervon, die ich nicht in irgendwelchen anderen Antworten, und die (nach der Programmierung in C # für 18 Jahre) erwähnt gesehen, die ich kann nicht glauben, ich wusste es nicht.

Wenn Sie eine Ausnahme von werfen oder auslösen jede Art in Ihrem catch Block (nicht nur seltsam StackOverflowExceptions und Dinge dieser ILK), und Sie müssen nicht den gesamten try/catch/finally Block in einem anderen Block try/catch Ihr finally Block wird nicht ausgeführt. Dies ist leicht demonstriert - und wenn ich es selbst nicht gesehen hatte, da, wie oft ich habe gelesen, dass es nur wirklich seltsam, winzige Ecke Fällen ist das ein finally Block verursachen kann nicht ausgeführt werden, würde ich es nicht geglaubt.

static void Main(string[] args)
{
    Console.WriteLine("Beginning demo of how finally clause doesn't get executed");
    try
    {
        Console.WriteLine("Inside try but before exception.");
        throw new Exception("Exception #1");
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Inside catch for the exception '{ex.Message}' (before throwing another exception).");
        throw;
    }
    finally
    {
        Console.WriteLine("This never gets executed, and that seems very, very wrong.");
    }

    Console.WriteLine("This never gets executed, but I wasn't expecting it to."); 
    Console.ReadLine();
}

Ich bin sicher ein Grund dafür gibt es, aber es ist seltsam, dass es mehr ist nicht bekannt. (Es ist darauf hingewiesen hier zum Beispiel, aber nicht überall in dieser besonderen Frage.)

Ich weiß, ich bin spät, um die Partei, sondern in dem Szenario (abweichend von dem Beispiel des OP), wo in der Tat eine Ausnahme MSDN Staaten ausgelöst wird ( https://msdn.microsoft.com/en-us/library/zwc8s4fz.aspx ): " Wenn die Ausnahme nicht abgefangen wird, wird die Ausführung der schließlich Block abhängt , ob das Betriebssystem eine Ausnahme entspannen Betrieb auszulösen wählt.“

Der finally-Block nur garantiert auszuführen, wenn eine andere Funktion (wie Haupt) weiter oben in dem Call-Stack die Ausnahme abfängt. Dieses Detail ist in der Regel kein Problem, da alle Laufzeitumgebungen (CLR und OS) auf freie meisten Ressourcen ausführen C # -Programme ein Prozess besitzt, wenn es austritt (Datei-Handles etc.). In einigen Fällen kann es jedoch von entscheidender Bedeutung sein: Eine Datenbank Betrieb Hälfte im Gange, die Sie bzw. begehen wollen. entspannen; oder eine Remote-Verbindung, die durch das Betriebssystem und blockiert dann einen Server kann nicht automatisch geschlossen.

Ja. Das ist in der Tat, dass Hauptpunkt einer finally-Anweisung. Es sei denn, etwas catestrophic (aus dem Speicher, Stecker herausgezogen, etc.) erfolgt die schließlich Anweisung sollte immer durchgeführt werden.

Es wird auch nicht auf abgefangene Ausnahme ausgelöst und in einem Windows-Dienst

in einem Thread gehostete läuft

schließlich nicht ausgeführt wird, wenn in einem Thread läuft in einem Windows-Dienst

schließlich wont im Falle laufen, wenn Sie aus der Anwendung verlässt mit System.exit (0); wie in

try
{
    System.out.println("try");
    System.exit(0);
}
finally
{
   System.out.println("finally");
}

das Ergebnis wäre nur: versuchen

99% der Szenarien wird sichergestellt sein, dass der Code innerhalb der finally Block laufen wird, aber denken Sie an dieses Szenario: Sie haben einen Thread, der einen try-> finally Block (kein catch) hat und Sie erhalten eine nicht behandelte Ausnahme in diesem Thread. In diesem Fall wird der Faden verlassen und sein finally Block nicht ausgeführt wird (kann die Anwendung auch weiterhin in diesem Fall laufen)

Dieses Szenario ist ziemlich selten, aber es ist nur zu zeigen, dass die Antwort nicht immer „Ja“ ist, ist es die meiste Zeit „Ja“, und manchmal, in seltenen Fällen, „Nein“.

Der Hauptzweck der finally-Block ist auszuführen, was in ihm geschrieben wird. Es sollte nicht davon abhängen, was auch immer passiert, in Versuch oder catch.However mit System.Environment.Exit (1) die Anwendung ohne sich zu bewegen, um nächste Codezeile verlassen wird.

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