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

其中,

  • exception-type 是新的 F# 異常型別的名稱。

  • argument-type 表示在引發此型別異常時可以提供的引數的型別。

  • 可以透過使用元組型別作為argument-type來指定多個引數。

try...with 表示式用於 F# 語言中的異常處理。

try … with 表示式的語法為:

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

以下程式顯示了使用簡單的 try… with 塊進行的基本異常處理:

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# 提供了一個exception 型別用於宣告異常。您可以在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 函式:

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 函式生成一個引數異常。以下程式演示了這一點:

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.
…

根據系統,還會顯示有關導致系統錯誤的檔案和變數的其他資訊。

廣告

© . All rights reserved.