Exceções: a expressão try...with

Este tópico descreve a expressão try...with, que é usada para manipulação de exceção em F#.

Sintaxe

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

Comentários

A expressão try...with é usada para manipular exceções em F#. É semelhante à instrução try...catch em C#. Na sintaxe anterior, o código em expression1 pode gerar uma exceção. A expressão try...with retorna um valor. Se nenhuma exceção for gerada, a expressão inteira retornará o valor de expression1. Se uma exceção for gerada, cada padrão será comparado com a exceção e, para o primeiro padrão correspondente, a expressão correspondente, conhecida como manipulador de exceção, desse branch será executada e a expressão geral retornará o valor da expressão nesse manipulador de exceção. Se nenhum padrão corresponder, a exceção será propagada na pilha de chamadas até que um manipulador correspondente seja encontrado. Os tipos dos valores retornados de cada expressão nos manipuladores de exceção devem corresponder ao tipo retornado pela expressão no bloco try.

Frequentemente, o fato de que um erro ocorreu também significa que não há valor válido que possa ser retornado das expressões em cada manipulador de exceção. Um padrão frequente é fazer com que o tipo da expressão seja um tipo de opção. O exemplo de código a seguir ilustra esse padrão.

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

let result1 = divide1 100 0

As exceções podem ser exceções do .NET ou de F#. É possível definir exceções de F# usando a palavra-chave exception.

É possível usar diversos padrões para filtrar o tipo de exceção e outras condições. As opções estão resumidas na tabela a seguir.

Padrão Descrição
:? exception-type Corresponde ao tipo de exceção do .NET especificado.
:? exception-type como identificador Corresponde ao tipo de exceção do .NET especificado, mas fornece um valor nomeado à exceção.
exception-name(arguments) Corresponde a um tipo de exceção de F# e associa os argumentos.
identifier Corresponde a qualquer exceção e associa o nome ao objeto de exceção. Equivalente ao identificador de :? System.Exception as
identificador quando condição Corresponde a qualquer exceção quando a condição é verdadeira.

Exemplos

Os exemplos de código a seguir ilustram o uso de diversos padrões de manipulador de exceção.

// This 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

// This version 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

// This version shows the use of F# exceptions.
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

Observação

O constructo try...with é uma expressão separada da expressão try...finally. Portanto, se o código exigir um bloco with e um bloco finally, será necessário aninhar as duas expressões.

Observação

É possível usar try...with em expressões assíncronas, expressões de tarefa e outras expressões de computação; nesse caso, uma versão personalizada da expressão try...with é usada. Para saber mais, confira Expressões assíncronas, Expressões de tarefa e Expressões de computação.

Confira também