Declarações de Importação: a palavra-chave open

Uma declaração de importação especifica um módulo ou namespace cujos elementos você pode referenciar sem usar um nome totalmente qualificado.

Sintaxe

open module-or-namespace-name
open type type-name

Comentários

Fazer referência ao código usando o namespace totalmente qualificado ou o caminho do módulo sempre pode criar um código difícil de escrever, ler e manter. Em vez disso, você pode usar a palavra-chave open para módulos e namespaces usados com frequência para que, ao fazer referência a um membro desse módulo ou namespace, você possa usar a forma abreviada do nome em vez do nome totalmente qualificado. Essa palavra-chave é semelhante à palavra-chave using em C#, using namespace no Visual C++ e Imports no Visual Basic.

O módulo ou namespace fornecido deve estar no mesmo projeto ou em um projeto ou assembly referenciado. Se não estiver, você poderá adicionar uma referência ao projeto ou usar a opção de linha de comando -reference (ou sua abreviação, -r). Para obter mais informações, consulte Opções do compilador.

A declaração de importação disponibiliza os nomes no código que segue a declaração, até o final do namespace, módulo ou arquivo delimitador.

Quando você usa várias declarações de importação, elas devem aparecer em linhas separadas.

O código a seguir mostra o uso da palavra-chave open para simplificar o código.

// Without the import declaration, you must include the full
// path to .NET Framework namespaces such as System.IO.
let writeToFile1 filename (text: string) =
  let stream1 = new System.IO.FileStream(filename, System.IO.FileMode.Create)
  let writer = new System.IO.StreamWriter(stream1)
  writer.WriteLine(text)

// Open a .NET Framework namespace.
open System.IO

// Now you do not have to include the full paths.
let writeToFile2 filename (text: string) =
  let stream1 = new FileStream(filename, FileMode.Create)
  let writer = new StreamWriter(stream1)
  writer.WriteLine(text)

writeToFile2 "file1.txt" "Testing..."

O compilador F# não emite um erro ou aviso se acontecerem ambiguidades quando o mesmo nome ocorre em mais de um módulo ou namespace aberto. Quando ocorrem ambiguidades, o F# dá preferência ao módulo ou namespace aberto mais recentemente. Por exemplo, no código a seguir, empty significa Seq.empty, embora empty esteja localizado nos módulos List e Seq.

open List
open Seq
printfn %"{empty}"

Portanto, tenha cuidado ao abrir módulos ou namespaces como List ou Seq que contêm membros com nomes idênticos; em vez disso, considere usar os nomes qualificados. Você deve evitar qualquer situação em que o código dependa da ordem das declarações de importação.

Declarações de tipo aberto

F# dá suporte a open em um tipo assim:

open type System.Math
PI

Isso vai expor todos os campos e membros estáticos acessíveis no tipo.

Você também pode open tipos de registro e união discriminada definidos em F# para expor membros estáticos. No caso de uniões discriminadas, você também pode expor os casos de união. Isso pode ser útil para acessar casos de união em um tipo declarado dentro de um módulo que você pode não querer abrir, assim:

module M =
    type DU = A | B | C

    let someOtherFunction x = x + 1

// Open only the type inside the module
open type M.DU

printfn "%A" A

Namespaces que são abertos por padrão

Alguns namespaces são usados com tanta frequência no código F# que são abertos implicitamente sem a necessidade de uma declaração de importação explícita. A tabela a seguir mostra os namespaces abertos por padrão.

Namespace Descrição
FSharp.Core Contém definições básicas de tipo F# para tipos internos, como int e float.
FSharp.Core.Operators Contém operações aritméticas básicas, como + e *.
FSharp.Collections Contém classes de coleção imutáveis, como List e Array.
FSharp.Control Contém tipos para construções de controle, como avaliação lenta e expressões assíncronas.
FSharp.Text Contém funções para E/S formatada, como a função printf.

Atributo AutoOpen

Você pode aplicar o atributo AutoOpen a um assembly se quiser abrir automaticamente um namespace ou módulo quando o assembly for referenciado. Você também pode aplicar o atributo AutoOpen a um módulo para abrir esse módulo automaticamente quando o módulo pai ou o namespace for aberto. Para obter mais informações, consulte AutoOpenAttribute.

Atributo RequireQualifiedAccess

Alguns módulos, registros ou tipos de união podem especificar o atributo RequireQualifiedAccess. Ao fazer referência a elementos desses módulos, registros ou uniões, você deve usar um nome qualificado, independentemente de incluir uma declaração de importação. Se usar esse atributo estrategicamente em tipos que definem nomes comumente usados, você ajudará a evitar colisões de nomes e, assim, tornará o código mais resiliente a alterações nas bibliotecas. Para obter mais informações, consulte RequireQualifiedAccessAttribute.

Confira também