Ich dachte, ich hätte verstanden, wie die Ausnahmebehandlung in C# funktioniert. Re-Lesen der Dokumentation für Spaß und Selbstvertrauen, habe ich auf Probleme stoßen:Ausnahmebehandlung (widersprüchliche Dokumentation/try-finally vs. Verwendung)
This document behauptet, dass die folgenden zwei Code-Schnipsel gleichwertig sind, noch mehr, dass die erste in die letztere zum Kompilieren übersetzt wird.
using (Font font1 = new Font("Arial", 10.0f)) {
byte charset = font1.GdiCharSet;
}
und
{
Font font1 = new Font("Arial", 10.0f);
try {
byte charset = font1.GdiCharSet;
}
finally {
if (font1 != null)
((IDisposable)font1).Dispose();
}
}
Darüber hinaus ist es behauptet:
Die using-Anweisung stellt sicher, dass Entsorgen auch genannt wird, wenn eine Ausnahme auftritt, während Sie Methoden für das Objekt aufrufen.
Im Gegensatz dazu that document heißt es:
Innerhalb einer behandelten Ausnahme der zugehörige
finally
Block garantiert ausgeführt werden soll. Wenn die Ausnahme jedoch nicht behandelt wird, hängt die Ausführung des Blocksfinally
davon ab, wie die Ausnahmeabwicklungsoperation ausgelöst wird.
Ich bekomme das nicht zusammen. Im Codebeispiel aus dem ersten Dokument ist die Ausnahme eindeutig nicht behandelt (da es keinen Catch-Block gibt). Wenn nun die Aussage aus dem zweiten Dokument wahr ist, ist der finally
Block nicht garantiert auszuführen. Dies widerspricht letztlich dem, was das erste Dokument sagt ("Die using
Erklärung sichert ...") (Hervorhebung von mir).
Also was ist die Wahrheit?
EDIT 1
ich es immer noch nicht. Die Antwort von StevieB hat mich dazu gebracht, mehr Teile aus der C# -Sprachspezifikation zu lesen. In Abschnitt 16.3 haben wir:
[...] Diese Suche wird fortgesetzt, bis eine Klausel Haken ist, dass die aktuelle Ausnahme behandeln kann gefunden [...] Sobald Klausel eine passende Raste gefunden, das System bereitet vor, die Kontrolle auf die erste Anweisung der Fangklausel zu übertragen. Bevor die Abarbeitung der catch-Klausel beginnt, führt das System zuerst in der Reihenfolge alle finally-Klauseln aus, die mit try-Anweisungen verschachtelten, die verschachtelter waren als die -Ausnahme.
So habe ich ein einfaches Testprogramm aus, das Code enthält, die von Null eine Division produziert und ist innerhalb eines try
Block.Diese Ausnahme ist nie in irgendwelchen meiner Code gefangen, aber die jeweiligen try
Anweisung hat einen finally
Block:
int b = 0;
try {
int a = 10/b;
}
finally {
MessageBox.Show("Hello");
}
zunächst entsprechend der Dokumentation Snippet oben, ich hatte erwartet, dass die finally
Block nie ausgeführt werden würde, und dass Das Programm würde einfach sterben, wenn es ohne angehängten Debugger ausgeführt würde. Aber das ist nicht der Fall; stattdessen wird das "Ausnahme-Dialogfeld", das wir alle zu gut kennen, angezeigt, und danach erscheint das Dialogfeld "Hello".
Nach einer Weile darüber nachgedacht und nach mit Lese docs, Artikel und Fragen wie this und that, wurde klar, dass dieses „Ausnahme Dialogfeld“ durch einen Standard-Exception-Handler erzeugt wird, die in Application.Run gebaut wird() und die anderen üblichen Methoden, die Ihr Programm "starten" könnten, so wundere ich mich nicht mehr warum der finally
Block ausgeführt wird.
Aber ich bin immer noch völlig verwirrt, weil der "Hallo" -Dialog erscheint nach die "Ausnahmedialogfeld". Das obige Dokumentations-Snippet ist ziemlich klar (naja, wahrscheinlich bin ich wieder einfach zu albern):
Die CLR findet keine catch
Klausel, die mit der try
Anweisung verbunden ist, wo die Division durch Null geschieht. Also sollte es die Ausnahme eine Ebene höher an den Aufrufer übergeben, wird dort auch keine passende catch
-Klausel finden (dort gibt es nicht einmal eine try
Aussage) und so weiter (wie oben erwähnt, handle ich nicht (dh fange) jede Ausnahme in diesem Testprogramm).
Schließlich sollte die Ausnahme die CLR-Standard Catch-All-Ausnahmebehandlung (dh diejenige, die standardmäßig in Application.Run() und seinen Freunden aktiv ist), aber (laut der oben genannten Dokumentation) sollte die CLR jetzt Führe alle finally
Blöcke aus, die tiefer verschachtelt sind als dieser Standard-Handler ("mein" finally
Block gehört zu diesen, nicht wahr?) vor Ausführung der CLR-Catch-All-Standard-Handler catch
Block.
Das bedeutet, dass der "Hallo" -Dialog sollte vor die "Ausnahmedialogfeld" angezeigt werden, nicht wahr ?. Nun, offensichtlich ist es umgekehrt. Könnte jemand das näher ausführen?
Es ist ein kleines bisschen unklar, was Sie fragen. Fragen Sie im Grunde, ob ein 'using' zu 100% disponieren wird? Wenn ja, hast du Recht, nein, es wird nicht (notwendigerweise), da es der Art von Ausnahme unterliegt, die während des Codes, den es enthält, ausgelöst wurde, ähnlich dem "Versuch fangen", du bist vielleicht vertrauter mit. –
Ich glaube, dass "unbehandelt" bedeutet, dass die Ausnahme von der Anwendung nicht behandelt wird, d. H. Die Ausnahme führt dazu, dass die Anwendung beendet wird/abstürzt. Da die Anwendung beendet wird, ist die Ausführung des finally-Blocks nicht unbedingt erforderlich. – StevieB
@ JᴀʏMᴇᴇ: Ich denke, er fragt, ob es möglich ist, dass ein 'finally' nicht auf unbehandelten Ausnahmen ausgeführt wird oder was _exception unwind operation_ bedeutet. Der Link [Unbehandelte Ausnahmeverarbeitung in der CLR] (http://go.microsoft.com/fwlink/?LinkId=128371) in [MSDN] (https://msdn.microsoft.com/en-us/library/zwc8s4fz .aspx) ist rot –