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.

Siehe auch