共用方式為


命名空間 (F#)

命名空間可讓您將程式代碼組織成相關功能區域,方法是讓您將名稱附加至 F# 程式專案群組。 命名空間通常是 F# 檔案中的最上層元素。

語法

namespace [rec] [parent-namespaces.]identifier

備註

如果您想要將程式代碼放在命名空間中,檔案中的第一個宣告必須宣告命名空間。 如果檔案中沒有其他命名空間宣告,則整個檔案的內容會成為命名空間的一部分。 如果是這種情況,則在下一個命名空間宣告之前,所有程式代碼都會被視為在第一個命名空間內。

命名空間不能直接包含值和函式。 相反地,值和函式必須包含在模組中,而且模組會包含在命名空間中。 命名空間可以包含類型和模組。

XML 檔批註可以宣告在命名空間上方,但會被忽略。 編譯程式指示詞也可以宣告在命名空間上方。

命名空間可以使用 namespace 關鍵詞明確宣告,或在宣告模組時以隱含方式宣告。 若要明確宣告命名空間,請使用命名空間關鍵詞後面接著命名空間名稱。 下列範例顯示程式代碼檔案,其宣告 Widgets 命名空間的類型和該命名空間中包含的模組。

namespace Widgets

type MyWidget1 =
    member this.WidgetName = "Widget1"

module WidgetsModule =
    let widgetName = "Widget2"

如果檔案的整個內容都在一個模組中,您也可以使用 module 關鍵詞隱含宣告命名空間,並在完整模塊名稱中提供新的命名空間名稱。 下列範例顯示宣告命名空間 Widgets 和模組 WidgetsModule的程式代碼檔案,其中包含函式。

module Widgets.WidgetModule

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

下列程式代碼相當於上述程式代碼,但模組是本機模組宣告。 在此情況下,命名空間必須出現在自己的行上。

namespace Widgets

module WidgetModule =

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

如果在一或多個命名空間的相同檔案中需要多個模組,您必須使用本機模組宣告。 當您使用本機模組宣告時,無法在模組宣告中使用限定命名空間。 下列程式代碼顯示具有命名空間宣告和兩個本機模組宣告的檔案。 在此情況下,模組會直接包含在命名空間中;沒有與檔案同名的隱含建立模組。 檔案中的任何其他程式代碼,例如 do 系結,都位於 命名空間中,但不在內部模組中,因此您必須使用模組名稱來限定模塊成員 widgetFunction

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

此範例的輸出如下所示。

Module1 10 20
Module2 5 6

如需詳細資訊,請參閱 模組

巢狀命名空間

當您建立巢狀命名空間時,必須完全限定它。 否則,您會建立新的最上層命名空間。 命名空間宣告中會忽略縮排。

下列範例示範如何宣告巢狀命名空間。

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"

檔案和元件中的命名空間

命名空間可以跨單一專案或編譯中的多個檔案。 命名空間片段一詞描述一個檔案中包含的命名空間部分。 命名空間也可以跨越多個元件。 例如, System 命名空間包含整個 .NET Framework,其跨越許多元件,而且包含許多巢狀命名空間。

全域命名空間

您可以使用預先定義的命名空間 global ,將名稱放在 .NET 最上層命名空間中。

namespace global

type SomeType() =
    member this.SomeMember = 0

您也可以使用全域來參考最上層 .NET 命名空間,例如,解決與其他命名空間的名稱衝突。

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

遞歸命名空間

命名空間也可以宣告為遞歸,以允許所有自主程式代碼相互遞歸。 這是透過 namespace rec來完成。 namespace rec使用 可減輕無法撰寫類型與模組之間相互引用程式代碼的一些痛苦。 以下是下列範例:

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 (banana: Banana) =
        let flip (banana: Banana) =
            match banana.Orientation with
            | Up ->
                banana.Orientation <- Down
                banana
            | Down -> banana

        // Update the peel state for all sides of the banana.
        let peelSides (banana: Banana) =
            banana.Sides
            |> List.map (function
                         | Unpeeled -> Peeled
                         | Peeled -> Peeled)

        // Apply the flipping and peeling logic based on the orientation.
        match banana.Orientation with
        | Up ->   banana |> flip |> peelSides
        | Down -> banana |> peelSides

請注意,例外狀況 DontSqueezeTheBananaException 和 類別 Banana 都彼此參考。 此外,模組 BananaHelpers 和類別 Banana 也會彼此參考。 如果您從MutualReferences命名空間中移除 rec 關鍵詞,則無法在 F# 中表示。

此功能也適用於最上層 模組

另請參閱