Share via


Namnområden (F#)

Med ett namnområde kan du ordna kod i områden med relaterade funktioner genom att koppla ett namn till en gruppering av F#-programelement. Namnområden är vanligtvis element på den översta nivån i F#-filer.

Syntax

namespace [rec] [parent-namespaces.]identifier

Kommentarer

Om du vill placera kod i ett namnområde måste den första deklarationen i filen deklarera namnområdet. Innehållet i hela filen blir sedan en del av namnområdet, förutsatt att det inte finns någon annan namnområdesdeklaration längre i filen. Om så är fallet anses all kod fram till nästa namnområdesdeklaration vara inom förnamnområdet.

Namnområden får inte innehålla värden och funktioner direkt. I stället måste värden och funktioner ingå i moduler, och moduler ingår i namnområden. Namnområden kan innehålla typer och moduler.

XML-dokumentkommentorer kan deklareras ovanför ett namnområde, men de ignoreras. Kompilatordirektiv kan också deklareras ovanför ett namnområde.

Namnområden kan deklareras explicit med nyckelordet för namnområdet, eller implicit när du deklarerar en modul. Om du vill deklarera ett namnområde explicit använder du nyckelordet för namnområdet följt av namnområdesnamnet. I följande exempel visas en kodfil som deklarerar ett namnområde Widgets med en typ och en modul som ingår i namnområdet.

namespace Widgets

type MyWidget1 =
    member this.WidgetName = "Widget1"

module WidgetsModule =
    let widgetName = "Widget2"

Om hela innehållet i filen finns i en modul kan du även deklarera namnområden implicit med hjälp av nyckelordet module och ange det nya namnområdesnamnet i det fullständigt kvalificerade modulnamnet. I följande exempel visas en kodfil som deklarerar ett namnområde Widgets och en modul WidgetsModule, som innehåller en funktion.

module Widgets.WidgetModule

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

Följande kod motsvarar föregående kod, men modulen är en lokal moduldeklaration. I så fall måste namnområdet visas på sin egen rad.

namespace Widgets

module WidgetModule =

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

Om mer än en modul krävs i samma fil i en eller flera namnområden måste du använda lokala moduldeklarationer. När du använder lokala moduldeklarationer kan du inte använda det kvalificerade namnområdet i moduldeklarationerna. Följande kod visar en fil som har en namnområdesdeklaration och två lokala moduldeklarationer. I det här fallet finns modulerna direkt i namnområdet. det finns ingen implicit skapad modul som har samma namn som filen. All annan kod i filen, till exempel en do bindning, finns i namnområdet men inte i de inre modulerna, så du måste kvalificera modulmedlemmen widgetFunction med hjälp av modulnamnet.

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

Utdata från det här exemplet är följande.

Module1 10 20
Module2 5 6

Mer information finns i Moduler.

Kapslade namnområden

När du skapar ett kapslat namnområde måste du kvalificera det fullt ut. Annars skapar du ett nytt toppnivånamnområde. Indrag ignoreras i namnområdesdeklarationer.

I följande exempel visas hur du deklarerar ett kapslat namnområde.

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"

Namnområden i filer och sammansättningar

Namnområden kan sträcka sig över flera filer i ett enda projekt eller en kompilering. Termen namnområdesfragment beskriver den del av ett namnområde som ingår i en fil. Namnområden kan också sträcka sig över flera sammansättningar. Namnområdet innehåller till exempel System hela .NET Framework, som sträcker sig över många sammansättningar och innehåller många kapslade namnområden.

Globalt namnområde

Du använder det fördefinierade namnområdet global för att placera namn i .NET-namnområdet på den översta nivån.

namespace global

type SomeType() =
    member this.SomeMember = 0

Du kan också använda global för att referera till .NET-namnområdet på den översta nivån, till exempel för att lösa namnkonflikter med andra namnområden.

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

Rekursiva namnområden

Namnrymder kan också deklareras som rekursiva så att all innesluten kod kan vara ömsesidigt rekursiv. Detta görs via namespace rec. Användning av namespace rec kan lindra vissa smärtor i att inte kunna skriva ömsesidigt referenskod mellan typer och moduler. Följande är ett exempel på detta:

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

Observera att både undantaget DontSqueezeTheBananaException och klassen Banana refererar till varandra. Dessutom refererar modulen BananaHelpers och klassen Banana till varandra. Detta skulle inte vara möjligt att uttrycka i F# om du tog bort nyckelordet recMutualReferences från namnområdet.

Den här funktionen är också tillgänglig för moduler på den översta nivån.

Se även