Bagikan melalui


Nameof

Ekspresi nameof menghasilkan konstanta string yang cocok dengan nama di sumber untuk hampir semua konstruksi F# di sumber.

Sintaksis

nameof symbol
nameof<'TGeneric>

Komentar

nameof bekerja dengan menyelesaikan simbol yang diteruskan ke dalamnya dan menghasilkan nama simbol itu seperti yang dinyatakan dalam kode sumber Anda. Ini berguna dalam berbagai skenario, seperti pengelogan, dan melindungi pengelogan Anda dari perubahan kode sumber.

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)

Baris terakhir akan melemparkan pengecualian dan "month" akan ditampilkan dalam pesan kesalahan.

Anda dapat mengambil nama hampir setiap konstruksi F#:

module M =
    let f x = nameof x

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

nameof bukan fungsi kelas satu dan tidak dapat digunakan seperti itu. Itu berarti tidak dapat diterapkan sebagian dan nilai tidak dapat disalurkan ke dalamnya melalui operator alur F#.

Nameof pada operator

Operator di F# dapat digunakan dengan dua cara, sebagai teks operator itu sendiri, atau simbol yang mewakili formulir yang dikompilasi. nameof pada operator akan menghasilkan nama operator seperti yang dinyatakan dalam sumber. Untuk mendapatkan nama yang dikompilasi, gunakan nama yang dikompilasi di sumber:

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

Nameof pada generik

Anda juga dapat mengambil nama parameter jenis generik, tetapi sintaksnya berbeda:

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

nameof<'TGeneric> akan mengambil nama simbol seperti yang didefinisikan dalam sumber, bukan nama jenis yang diganti di situs panggilan.

Alasan mengapa sintaksnya berbeda adalah untuk menyelaraskan dengan operator intrinsik F# lainnya seperti typeof<> dan typedefof<>. Ini membuat F# konsisten sehubungan dengan operator yang bertindak berdasarkan jenis generik dan apa pun di sumber.

Nameof dalam pencocokan pola

Pola ini nameof memungkinkan Anda menggunakan nameof dalam ekspresi kecocokan pola. Ini sangat berguna saat mencocokkan nilai string dengan nama simbol dalam kode Anda, memberikan keamanan waktu kompilasi dan pembaruan otomatis saat Anda merefaktor.

Contoh praktis adalah mendeserialisasi peristiwa atau pesan di mana nilai string mewakili nama jenis atau kasus:

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

Menggunakan nameof alih-alih literal string seperti "OrderCreated" memberikan beberapa manfaat:

  • Jika Anda mengganti nama kasus serikat yang didiskriminasi, pola akan diperbarui secara otomatis.
  • Pengkompilasi mencegah kesalahan ketik dengan memastikan simbol ada.
  • Kode Anda tetap konsisten selama pemfaktoran ulang.

Anda juga dapat menggunakan nameof dengan parameter:

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 dengan anggota instans

F# memerlukan instans untuk mengekstrak nama anggota instans dengan nameof. Jika instans tidak mudah tersedia, maka instans dapat diperoleh menggunakan 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