Partilhar via


Namespaces (F#)

Um namespace permite organizar o código em áreas de funcionalidade relacionada, permitindo que você anexe um nome a um agrupamento de elementos de programa F#. Namespaces são normalmente elementos de nível superior em arquivos F#.

Sintaxe

namespace [rec] [parent-namespaces.]identifier

Observações

Se você quiser colocar código em um namespace, a primeira declaração no arquivo deve declarar o namespace. O conteúdo do arquivo inteiro então se torna parte do namespace, desde que nenhuma outra declaração de namespaces exista mais no arquivo. Se esse for o caso, todo o código até a próxima declaração de namespace é considerado como estando dentro do primeiro namespace.

Os namespaces não podem conter diretamente valores e funções. Em vez disso, valores e funções devem ser incluídos em módulos e módulos são incluídos em namespaces. Os namespaces podem conter tipos e módulos.

Os comentários do documento XML podem ser declarados acima de um namespace, mas são ignorados. As diretivas do compilador também podem ser declaradas acima de um namespace.

Os namespaces podem ser declarados explicitamente com a palavra-chave namespace ou implicitamente ao declarar um módulo. Para declarar um namespace explicitamente, use a palavra-chave namespace seguida pelo nome do namespace. O exemplo a seguir mostra um arquivo de código que declara um namespace Widgets com um tipo e um módulo incluídos nesse namespace.

namespace Widgets

type MyWidget1 =
    member this.WidgetName = "Widget1"

module WidgetsModule =
    let widgetName = "Widget2"

Se todo o conteúdo do arquivo estiver em um módulo, você também poderá declarar namespaces implicitamente usando a module palavra-chave e fornecendo o novo nome de namespace no nome do módulo totalmente qualificado. O exemplo a seguir mostra um arquivo de código que declara um namespace Widgets e um módulo WidgetsModule, que contém uma função.

module Widgets.WidgetModule

let widgetFunction x y =
   printfn "%A %A" x y

O código a seguir é equivalente ao código anterior, mas o módulo é uma declaração de módulo local. Nesse caso, o namespace deve aparecer em sua própria linha.

namespace Widgets

module WidgetModule =

    let widgetFunction x y =
        printfn "%A %A" x y

Se mais de um módulo for necessário no mesmo arquivo em um ou mais namespaces, você deverá usar declarações de módulo local. Quando você usa declarações de módulo local, não pode usar o namespace qualificado nas declarações de módulo. O código a seguir mostra um arquivo que tem uma declaração de namespace e duas declarações de módulo local. Nesse caso, os módulos estão contidos diretamente no namespace; Não há nenhum módulo criado implicitamente que tenha o mesmo nome que o arquivo. Qualquer outro código no arquivo, como uma do ligação, está no namespace, mas não nos módulos internos, portanto, você precisa qualificar o membro widgetFunction do módulo usando o nome do módulo.

namespace Widgets

module WidgetModule1 =
   let widgetFunction x y =
      printfn "Module1 %A %A" x y
module WidgetModule2 =
   let widgetFunction x y =
      printfn "Module2 %A %A" x y

module useWidgets =

  do
     WidgetModule1.widgetFunction 10 20
     WidgetModule2.widgetFunction 5 6

A saída deste exemplo é a seguinte.

Module1 10 20
Module2 5 6

Para obter mais informações, consulte Módulos.

Namespaces aninhados

Ao criar um namespace aninhado, você deve qualificá-lo totalmente. Caso contrário, você criará um novo namespace de nível superior. O recuo é ignorado nas declarações de namespace.

O exemplo a seguir mostra como declarar um namespace aninhado.

namespace Outer

    // Full name: Outer.MyClass
    type MyClass() =
       member this.X(x) = x + 1

// Fully qualify any nested namespaces.
namespace Outer.Inner

    // Full name: Outer.Inner.MyClass
    type MyClass() =
       member this.Prop1 = "X"

Namespaces em arquivos e assemblies

Os namespaces podem abranger vários arquivos em um único projeto ou compilação. O termo fragmento de namespace descreve a parte de um namespace incluída em um arquivo. Os namespaces também podem abranger vários assemblies. Por exemplo, o System namespace inclui todo o .NET Framework, que abrange muitos assemblies e contém muitos namespaces aninhados.

Espaço de nomes global

Você usa o namespace global predefinido para colocar nomes no namespace de nível superior do .NET.

namespace global

type SomeType() =
    member this.SomeMember = 0

Você também pode usar global para fazer referência ao namespace .NET de nível superior, por exemplo, para resolver conflitos de nome com outros namespaces.

global.System.Console.WriteLine("Hello World!")

Namespaces recursivos

Os namespaces também podem ser declarados como recursivos para permitir que todo o código contido seja mutuamente recursivo. Isto é feito através do namespace rec. O uso de pode aliviar algumas dores em não ser capaz de namespace rec escrever código mutuamente referencial entre tipos e módulos. Segue-se um exemplo disso:

namespace rec MutualReferences

type Orientation = Up | Down
type PeelState = Peeled | Unpeeled

// This exception depends on the type below.
exception DontSqueezeTheBananaException of Banana

type Banana(orientation : Orientation) =
    member val IsPeeled = false with get, set
    member val Orientation = orientation with get, set
    member val Sides: PeelState list = [ Unpeeled; Unpeeled; Unpeeled; Unpeeled] with get, set

    member self.Peel() = BananaHelpers.peel self // Note the dependency on the BananaHelpers module.
    member self.SqueezeJuiceOut() = raise (DontSqueezeTheBananaException self) // This member depends on the exception above.

module BananaHelpers =
    let peel (b: Banana) =
        let flip (banana: Banana) =
            match banana.Orientation with
            | Up ->
                banana.Orientation <- Down
                banana
            | Down -> banana

        let peelSides (banana: Banana) =
            banana.Sides
            |> List.map (function
                         | Unpeeled -> Peeled
                         | Peeled -> Peeled)

        match b.Orientation with
        | Up ->   b |> flip |> peelSides
        | Down -> b |> peelSides

Observe que a exceção DontSqueezeTheBananaException e a classe Banana se referem uma à outra. Além disso, o módulo BananaHelpers e a classe Banana também se referem um ao outro. Isso não seria possível expressar em F# se você removesse a recMutualReferences palavra-chave do namespace.

Este recurso também está disponível para módulos de nível superior.

Consulte também