次の方法で共有


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# の演算子は、演算子テキスト自体として、またはコンパイル済みのフォームを表すシンボルとして、2 つの方法で使用できます。 nameof 演算子では、ソースで宣言されている演算子の名前が生成されます。 コンパイルされた名前を取得するには、ソースでコンパイル済みの名前を使用します。

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

ジェネリックの Nameof

ジェネリック型パラメーターの名前を取得することもできますが、構文は異なります。

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

nameof<'TGeneric> は、呼び出しサイトで置換された型の名前ではなく、ソースで定義されているシンボルの名前を受け取ります。

構文が異なる理由は、 typeof<>typedefof<>などの他の F# 組み込み演算子と一致するためです。 これにより、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

"OrderCreated"のような文字列リテラルの代わりにnameofを使用すると、いくつかの利点があります。

  • 判別共用体ケースの名前を変更すると、パターンは自動的に更新されます。
  • コンパイラは、シンボルが存在することを確認することで、入力ミスを防ぎます。
  • リファクタリング中もコードの一貫性は維持されます。

パラメーターで 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