共用方式為


Nameof

表達式 nameof 會產生字串常數,其符合來源中幾乎任何 F# 建構的來源名稱。

語法

nameof symbol
nameof<'TGeneric>

備註

nameof 可藉由解析傳遞給它的符號,並在原始程式碼中宣告該符號時產生該符號的名稱。 這在各種案例中很有用,例如記錄,並保護您的記錄免於原始程式碼中的變更。

let months =
    [
        "January"; "February"; "March"; "April";
        "May"; "June"; "July"; "August"; "September";
        "October"; "November"; "December"
    ]

let lookupMonth month =
    if (month > 12 || month < 1) then
        invalidArg (nameof month) ($"Value passed in was %d{month}.")

    months[month-1]

printfn "%s" (lookupMonth 12)
printfn "%s" (lookupMonth 1)
printfn "%s" (lookupMonth 13)

最後一行會擲回例外狀況,並 "month" 會顯示在錯誤訊息中。

您可以取得幾乎每個 F# 建構的名稱:

module M =
    let f x = nameof x

printfn $"{(M.f 12)}"
printfn $"{(nameof M)}"
printfn $"{(nameof M.f)}"

nameof 不是一流的函式,因此無法使用。 這表示無法部分套用它,而且值無法透過 F# 管線運算子輸送到其中。

運算子上的 Nameof

F# 中的運算符可以使用兩種方式,做為運算符文字本身,或代表已編譯窗體的符號。 nameof 運算子上會產生運算子的名稱,因為它在來源中宣告。 若要取得編譯的名稱,請使用來源中的已編譯名稱:

nameof(+) // "+"
nameof op_Addition // "op_Addition"

泛型上的 Nameof

您也可以採用泛型類型參數的名稱,但語法不同:

let f<'a> () = nameof<'a>
f() // "a"

nameof<'TGeneric> 會採用來源中所定義的符號名稱,而不是在呼叫月臺取代的類型名稱。

語法不同的原因是要與其他 F# 內建運算元一致,例如 typeof<>typedefof<>。 這可讓 F# 與在泛型型別上運作的運算符以及來源中的其他任何動作保持一致。

模式比對中的 Nameof

nameof 模式 可讓您在 nameof 模式比對運算式中使用。 當將字串值與程式碼中的符號名稱進行比對時,這特別有用,可在您重構時提供編譯時安全性和自動更新。

一個實際範例是還原序列化事件或訊息,其中字串值代表類型或案例名稱:

type EventType =
    | OrderCreated
    | OrderShipped
    | OrderDelivered

let handleEvent eventName data =
    match eventName with
    | nameof OrderCreated -> printfn "Processing order creation: %s" data
    | nameof OrderShipped -> printfn "Processing order shipment: %s" data
    | nameof OrderDelivered -> printfn "Processing order delivery: %s" data
    | _ -> printfn "Unknown event type: %s" eventName

handleEvent "OrderCreated" "Order #123" // matches first case

使用 nameof instead of string literal like "OrderCreated" 提供數個優點:

  • 如果您重新命名區分聯集案例,則型樣會自動更新。
  • 編譯器會確保符號存在,以防止拼字錯誤。
  • 您的程式碼在重構期間保持一致。

您也可以搭配參數使用 nameof

let f (str: string) =
    match str with
    | nameof str -> "It's 'str'!"
    | _ -> "It is not 'str'!"

f "str" // matches
f "asdf" // does not match

具有實例成員的 Nameof

F# 需要 實例,才能使用 nameof來擷取實例成員的名稱。 如果實例不容易使用,則可以使用 Unchecked.defaultof取得實例。

type MyRecord = { MyField: int }
type MyClass() =
    member _.MyProperty = ()
    member _.MyMethod () = ()

nameof Unchecked.defaultof<MyRecord>.MyField   // MyField
nameof Unchecked.defaultof<MyClass>.MyProperty // MyProperty
nameof Unchecked.defaultof<MyClass>.MyMethod   // MyMethod