При возникновении исключительной ситуации, например, при делении на ноль или при обращении по недействительному индексу в списке, программа автоматически генерирует исключения. Однако в каких-то ситуациях может потребоваться дополнительно сгенерировать исключение. В F# для этого применяется функциия raise. Она позволяет вручную сгенерировать исключение в любом месте программы и имеет следующий синтаксис:
raise (выражение)
В скобках передается выражение, которое возвращает объект исключения. Например, в зависимости от переданного в функцию возраста надо вывести возрастную группу:
let checkAge age = if (age < 1 || age > 110) then raise(new System.Exception("Invalid age!")) if age > 60 then printfn "Old" else if age > 35 then printfn "Middle age" else if age > 17 then printfn "Young" else printfn "Child" checkAge 26 checkAge 100500 checkAge 46
В качестве возраста в функцию можно передать любое число, в том числе очень большое или отрицательное. Соответственно, не любое значение будет представлять действительный возраст. Поэтому вначале проверяем на соответствие параметра допутимому диапазону (пусть это будет диапазон от 1 до 110). И если параметр вне этого диапазона, то генерируем исключение типа System.Exception:
if (age < 1 || age > 110) then raise(new System.Exception("Invalid age!"))
В конструкор класса передается сообщение об исключении.
Таким образом, при передаче недействительного возраста будет сгенерировано исключение, и программа аварийно завершится:
checkAge 100500 // Генерация исключения, и программа падает
Подобное исключение мы также можем обработать с помощью конструкции try..with:
let checkAge age = try if (age < 1 || age > 110) then raise(new System.Exception("Invalid age!")) if age > 60 then printfn "Old" else if age > 35 then printfn "Middle age" else if age > 17 then printfn "Young" else printfn "Child" with | ex -> printfn "%s" ex.Message checkAge 26 // Young checkAge 100500 // Invalid age! checkAge 46 // Middle age
Функцию reraise можно использовать в блоке with для распространения обработанного исключения вверх по цепочке вызовов. reraise не принимает параметров и может применяться когда надо передать информацию об обработанном исключении во внешний код. Например:
let checkAge age = try if (age < 1 || age > 110) then raise(new System.Exception("Invalid age!")) if age > 60 then printfn "Old" else if age > 35 then printfn "Middle age" else if age > 17 then printfn "Young" else printfn "Child" with | ex -> printfn "CheckAge function: %s" ex.Message reraise() try checkAge 26 // Young checkAge 100500 // Генерируется исключение checkAge 46 // Не выполняется with | ex -> printfn "External code: %s" ex.Message
Здесь вне функции checkAge определяем еще одну конструкцию try..with, где перехватываем исключение, поднятое из функции checkAge. Консольный вывод:
Young CheckAge function: Invalid age! External code: Invalid age!
Еще один способ генерации исключения в F# представляет функция failwith, которая принимает строку сообщения об исключении:
failwith сообщение_об_исключении
В реальности эта функция создает объект исключения System.Exception
, в конструктор которого передается сообщение об исключении. Например:
let checkAge age = try if (age < 1 || age > 110) then failwith "Invalid age!" if age > 60 then printfn "Old" else if age > 35 then printfn "Middle age" else if age > 17 then printfn "Young" else printfn "Child" with | ex -> printfn "CheckAge function: %s" ex.Message checkAge 26 // Young checkAge 100500 // Invalid age! checkAge 46 // Middle age
Функция invalidArg применяется исключения, связанного с аргументом функции. invalidArg
имеет следующую форму:
invalidArg имя_параметра сообщение_об_исключении
Применение:
let checkAge age = try if (age < 1 || age > 110) then invalidArg "age" "Value out of the range" if age > 60 then printfn "Old" else if age > 35 then printfn "Middle age" else if age > 17 then printfn "Young" else printfn "Child" with | ex -> printfn "%s" ex.Message checkAge 26 // Young checkAge 100500 // Value out of the range (Parameter 'age')