F# - 异常处理

异常是在执行程序期间出现的问题. F#异常是对程序运行时出现的异常情况的响应,例如尝试除以零.

异常提供了一种从一个部分转移控制的方法程序到另一个. F#异常处理提供以下构造 :

构造描述
raise expr引发给定的异常.
failwith expr引发 System.Exception 异常.
try expr with rules捕获符合模式规则的表达式.
try expr finally expr在计算成功和引发异常时执行 finally 表达式.
| :? ArgumentException与给定.NET异常类型匹配的规则.
| :? ArgumentException as e匹配给定.NET异常类型的规则,将名称 e 绑定到异常对象值.
|Failure(msg) →  expr匹配给定数据携带F#异常的规则.
| exn →  expr匹配任何异常的规则,将名称 exn 绑定到异常对象值.
|exn when expr → expr在给定条件下匹配异常的规则,将名称 exn 绑定到异常对象值.

让我们从异常处理的基本语法开始.

语法

F#异常处理块的基本语法是 :

exception exception-type of argument-type


其中,

  • 例外类型是一个名称新的F#异常类型.

  • 参数类型表示当您引发此异常时可以提供的参数类型类型.

  • 可以使用参数类型的元组类型指定多个参数.

try ... with 表达式用于F#语言中的异常处理.

try ... with expression的语法是 :

try
   expression1
with
   | pattern1 -> expression2
   | pattern2 -> expression3
...


try ... finally 表达式允许您执行清理代码,即使一段代码抛出一个异常.

try ... finally表达式的语法是 :

try
   expression1
finally
   expression2


raise 函数用于表示发生错误或异常情况.它还捕获有关异常对象中的错误的信息.

raise函数的语法是 :

raise(expression)


failwith 函数生成F#异常.

failwith函数的语法是 :

failwith error-message-string


invalidArg 函数生成参数异常.

invalidArg parameter-name error-message-string


异常处理示例

示例1

以下程序显示使用简单的尝试进行基本的异常处理...使用块:

let divisionprog x y =
   try
      Some (x / y)
   with
      | :? System.DivideByZeroException -> printfn "Division by zero!"; None

let result1 = divisionprog 100 0


编译并执行程序时,它会产生以下输出 :

Division by zero!

示例2

F#提供了一个异常类型来声明异常.您可以在 try ... with 表达式中直接在过滤器中使用异常类型.

以下示例演示了此 :

exception Error1 of string
// Using a tuple type as the argument type.
exception Error2 of string * int

let myfunction x y =
   try
      if x = y then raise (Error1("Equal Number Error"))
      else raise (Error2("Error Not detected", 100))
   with
      | Error1(str) -> printfn "Error1 %s" str
      | Error2(str, i) -> printfn "Error2 %s %d" str i
myfunction 20 10
myfunction 5 5


编译执行程序时,它产生以下输出 :

Error2 Error Not detected 100
Error1 Equal Number Error


示例3

以下示例演示嵌套异常处理 :

exception InnerError of string
exception OuterError of string

let func1 x y =
   try
      try
         if x = y then raise (InnerError("inner error"))
         else raise (OuterError("outer error"))
      with
         | InnerError(str) -> printfn "Error:%s" str
   finally
      printfn "From the finally block."

let func2 x y =
   try
      func1 x y
   with
      | OuterError(str) -> printfn "Error: %s" str

func2 100 150
func2 100 100
func2 100 120


编译并执行程序时,它会产生以下输出 :

From the finally block.
Error: outer error
Error:inner error
From the finally block.
From the finally block.
Error: outer error


示例4

以下函数演示了 failwith function :

let divisionFunc x y =
   if (y = 0) then failwith "Divisor cannot be zero."
   else
      x / y

let trydivisionFunc x y =
   try
      divisionFunc x y
   with
      | Failure(msg) -> printfn "%s" msg; 0

let result1 = trydivisionFunc 100 0
let result2 = trydivisionFunc 100 4
printfn "%A" result1
printfn "%A" result2


编译并执行程序时,它会产生以下输出 :

Divisor cannot be zero.
0
25


示例5

invalidArg function生成一个参数异常.以下程序演示了这个 :

let days = [| "Sunday"; "Monday"; "Tuesday"; "Wednesday"; "Thursday"; "Friday"; "Saturday" |]
let findDay day =
   if (day > 7 || day < 1)
      then invalidArg "day" (sprintf "You have entered %d." day)
   days.[day - 1]

printfn "%s" (findDay 1)
printfn "%s" (findDay 5)
printfn "%s" (findDay 9)


编译并执行程序时,它会产生以下输出 :

Sunday
Thursday
Unhandled Exception:
System.ArgumentException: You have entered 9.
…


根据系统的不同,还将显示有关导致系统错误的文件和变量的其他信息.