Exception handling is the standard way of handling error conditions in the .NET Framework. Thus, any .NET language must support this mechanism, including F#.
try...with expression is used for exception handling in the F# language.try...finally expression enables you to execute clean-up code even if a block of code throws an exception.try...with ExpressionThe basic syntax of the try...with expression is as follows.
try
expression1
with
| pattern1 -> expression2
| pattern2 -> expression3
...
The try...with expression is used to handle exceptions in F#. It is similar to the try...catch statement in C#.
expression1 might generate an exception.try...with expression returns a value, if no exception is thrown, the whole expression returns the value of expression1.The following example shows the usage of the try...with expression.
let divide1 x y =
try
Some (x / y)
with
| :? System.DivideByZeroException -> printfn "Division by zero!"; None
let result1 = divide1 100 0
Exceptions can be .NET exceptions, or they can be F# exceptions. You can define F# exceptions by using the exception keyword.
You can use a variety of patterns to filter on the exception type and other conditions as shown below.
| Pattern | Description |
|---|---|
:? exception-type |
Matches the specified .NET exception type. |
:? exception-type as identifier |
Matches the specified .NET exception type, but gives the exception a named value. |
exception-name(arguments) |
Matches an F# exception type and binds the arguments. |
identifier |
Matches any exception and binds the name to the exception object. Equivalent to :? System.Exception as identifier |
identifier when condition |
Matches any exception if the condition is true. |
The following example shows the use of the as keyword to assign a name to a .NET exception.
let divide2 x y =
try
Some( x / y )
with
| :? System.DivideByZeroException as ex -> printfn "Exception! %s " (ex.Message); None
let result2 = divide1 100 0
The following example shows the use of a condition to branch to multiple paths with the same exception.
let divide3 x y flag =
try
x / y
with
| ex when flag -> printfn "TRUE: %s" (ex.ToString()); 0
| ex when not flag -> printfn "FALSE: %s" (ex.ToString()); 1
let result2 = divide3 100 0 true
You can also use the F# exceptions as shown in the below example.
exception Error1 of string
exception Error2 of string * int
let function1 x y =
try
if x = y then raise (Error1("x"))
else raise (Error2("x", 10))
with
| Error1(str) -> printfn "Error1 %s" str
| Error2(str, i) -> printfn "Error2 %s %d" str i
function1 10 10
function1 9 2
try...finally ExpressionThe basic syntax of the try...finally expression is as follows.
try
expression1
finally
expression2
The try...finally expression can be used to execute the code in expression2 regardless of whether an exception is generated during the execution of expression1.
The following example shows the usage of the try...finally expression.
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
The try...with is a separate construct from the try...finally construct. Therefore, if your code requires both, you have to nest the two constructs as shown below.
exception InnerError of string
exception OuterError of string
let function2 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 function3 x y =
try
function2 x y
with
| OuterError(str) -> printfn "Error2 %s" str
function3 100 100
function3 100 10