Ausnahmen: Der try...finally-Ausdruck
Mit dem try...finally
-Ausdruck können Sie Bereinigungscode auch dann ausführen, wenn ein Codeblock eine Ausnahme auslöst.
Syntax
try
expression1
finally
expression2
Bemerkungen
Der try...finally
-Ausdruck kann verwendet werden, um den Code in Ausdruck2 in der vorherigen Syntax auszuführen, unabhängig davon, ob während der Ausführung von Ausdruck1 eine Ausnahme generiert wird.
Der Typ von Ausdruck2 trägt nicht zum Wert des gesamten Ausdrucks bei. Der Typ, der zurückgegeben wird, wenn keine Ausnahme auftritt, ist der letzte Wert in Ausdruck1. Wenn eine Ausnahme auftritt, wird kein Wert zurückgegeben und der Ablauf der Steuerung wird an den nächsten übereinstimmenden Ausnahmehandler des Aufrufstapels übertragen. Wenn kein Ausnahmehandler gefunden wird, wird das Programm beendet. Bevor der Code in einem übereinstimmenden Handler ausgeführt oder das Programm beendet wird, wird der Code im finally
-Branch ausgeführt.
Das folgende Codebeispiel veranschaulicht die Verwendung des try...finally
-Ausdrucks.
let divide x y =
let stream : System.IO.FileStream = System.IO.File.Create("test.txt")
let writer : System.IO.StreamWriter = new System.IO.StreamWriter(stream)
try
writer.WriteLine("test1")
Some( x / y )
finally
writer.Flush()
printfn "Closing stream"
stream.Close()
let result =
try
divide 100 0
with
| :? System.DivideByZeroException -> printfn "Exception handled."; None
Die Ausgabe an die Konsole lautet wie folgt.
Closing stream
Exception handled.
Wie Sie in der Ausgabe sehen können, wurde der Stream geschlossen, bevor die äußere Ausnahme behandelt wurde, und die Datei test.txt
enthält den Text test1
, der angibt, dass die Puffer geleert und auf den Datenträger geschrieben wurden, obwohl die Ausnahme die Kontrolle an den äußeren Ausnahmehandler übertragen hat.
Beachten Sie, dass das try...with
-Konstrukt ein vom Konstrukt getrenntes try...finally
-Konstrukt ist. Wenn Ihr Code also sowohl einen with
-Block als auch einen finally
-Block erfordert, müssen Sie die beiden Konstrukte wie im folgenden Codebeispiel verschachteln.
exception InnerError of string
exception OuterError of string
let function1 x y =
try
try
if x = y then raise (InnerError("inner"))
else raise (OuterError("outer"))
with
| InnerError(str) -> printfn "Error1 %s" str
finally
printfn "Always print this."
let function2 x y =
try
function1 x y
with
| OuterError(str) -> printfn "Error2 %s" str
function2 100 100
function2 100 10
Im Kontext von Berechnungsausdrücken, einschließlich Sequenzausdrücken und asynchronen Ausdrücken, können try...finally Ausdrücke über eine benutzerdefinierte Implementierung verfügen. Weitere Informationen finden Sie unter Berechnungsausdrücke.