Ich bin fast sicher, dass die Antwort JA ist. Wenn ich einen Try finally-Block verwende, aber keinen Catch-Block verwende, sprudeln alle Ausnahmen. Richtig?
Irgendwelche Gedanken zur Praxis im Allgemeinen?
Seth
Ich bin fast sicher, dass die Antwort JA ist. Wenn ich einen Try finally-Block verwende, aber keinen Catch-Block verwende, sprudeln alle Ausnahmen. Richtig?
Irgendwelche Gedanken zur Praxis im Allgemeinen?
Seth
Antworten:
Ja, das wird es absolut. Angenommen, Ihr finally
Block löst natürlich keine Ausnahme aus. In diesem Fall "ersetzt" dies effektiv die ursprünglich ausgelöste.
Irgendwelche Gedanken zur Praxis im Allgemeinen?
Ja. Sei vorsichtig . Wenn Ihr finally-Block ausgeführt wird, ist es durchaus möglich, dass er ausgeführt wird, da eine nicht behandelte, unerwartete Ausnahme ausgelöst wurde . Das bedeutet, dass etwas kaputt ist und etwas völlig Unerwartetes passieren kann.
In dieser Situation ist es wohl der Fall, dass Sie Code überhaupt nicht in endgültigen Blöcken ausführen sollten. Der Code im finally-Block kann so erstellt werden, dass angenommen wird, dass Subsysteme, von denen er abhängt, fehlerfrei sind, obwohl sie tatsächlich stark beschädigt werden können. Der Code im finally-Block könnte die Situation verschlimmern.
Zum Beispiel sehe ich oft so etwas:
DisableAccessToTheResource();
try
{
DoSomethingToTheResource();
}
finally
{
EnableAccessToTheResource();
}
Der Autor dieses Codes denkt: "Ich mache eine vorübergehende Mutation zum Zustand der Welt. Ich muss den Zustand wieder so machen, wie er war, bevor ich gerufen wurde." Aber lassen Sie uns über alle Möglichkeiten nachdenken, wie dies schief gehen könnte.
Erstens könnte der Anrufer den Zugriff auf die Ressource bereits deaktivieren. In diesem Fall wird es durch diesen Code möglicherweise vorzeitig wieder aktiviert.
Zweitens, wenn DoSomethingToTheResource eine Ausnahme auslöst, ist es richtig, den Zugriff auf die Ressource zu ermöglichen? Der Code, der die Ressource verwaltet, ist unerwartet fehlerhaft . In diesem Code heißt es tatsächlich: "Wenn der Verwaltungscode fehlerhaft ist, stellen Sie sicher, dass anderer Code diesen fehlerhaften Code so schnell wie möglich aufrufen kann, damit er auch schrecklich fehlschlägt ." Das scheint eine schlechte Idee zu sein.
Drittens, wenn DoSomethingToTheResource eine Ausnahme auslöst, woher wissen wir dann, dass EnableAccessToTheResource nicht auch eine Ausnahme auslöst? Welche Schrecklichkeit sich auch auf die Verwendung der Ressource auswirkt, kann sich auch auf den Bereinigungscode auswirken. In diesem Fall geht die ursprüngliche Ausnahme verloren und das Problem ist schwerer zu diagnostizieren.
Ich neige dazu, Code wie diesen zu schreiben, ohne try-finally-Blöcke zu verwenden:
bool wasDisabled = IsAccessDisabled();
if (!wasDisabled)
DisableAccessToTheResource();
DoSomethingToTheResource();
if (!wasDisabled)
EnableAccessToTheResource();
Jetzt ist der Staat nicht mutiert, es sei denn, es muss sein. Jetzt wird der Status des Anrufers nicht durcheinander gebracht. Und jetzt, wenn DoSomethingToTheResource fehlschlägt, aktivieren wir den Zugriff nicht erneut. Wir gehen davon aus, dass etwas zutiefst kaputt ist, und riskieren nicht, die Situation zu verschlimmern, indem wir versuchen, weiterhin Code auszuführen. Lassen Sie den Anrufer das Problem lösen, wenn er kann.
Wann ist es also eine gute Idee, einen finally-Block auszuführen? Erstens, wenn die Ausnahme erwartet wird. Beispielsweise können Sie erwarten, dass ein Versuch, eine Datei zu sperren, fehlschlägt, weil jemand anderes sie gesperrt hat. In diesem Fall ist es sinnvoll, die Ausnahme abzufangen und dem Benutzer zu melden. In diesem Fall wird die Unsicherheit darüber, was kaputt ist, verringert; Es ist unwahrscheinlich, dass Sie die Situation durch Aufräumen verschlimmern.
Zweitens, wenn die Ressource, die Sie bereinigen, eine knappe Systemressource ist. Beispielsweise ist es sinnvoll, ein Dateihandle in einem finally-Block zu schließen. (Eine "Verwendung" ist natürlich nur eine andere Möglichkeit, einen Try-finally-Block zu schreiben.) Der Inhalt der Datei ist möglicherweise beschädigt, aber Sie können jetzt nichts dagegen tun. Das Dateihandle wird irgendwann geschlossen, also kann es auch eher früher als später sein.