Nameof

L'espressione nameof produce una costante stringa che corrisponde al nome nell'origine per quasi qualsiasi costrutto F# nell'origine.

Sintassi

nameof symbol
nameof<'TGeneric>

Osservazioni:

nameof funziona risolvendo il simbolo passato e produce il nome di tale simbolo come dichiarato nel codice sorgente. Ciò è utile in vari scenari, ad esempio la registrazione e protegge la registrazione dalle modifiche apportate al codice sorgente.

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)

L'ultima riga genererà un'eccezione e "month" verrà visualizzata nel messaggio di errore.

È possibile prendere il nome di quasi ogni costrutto F#:

module M =
    let f x = nameof x

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

nameof non è una funzione di prima classe e non può essere usata come tale. Ciò significa che non può essere applicato parzialmente e i valori non possono essere inviati tramite pipe tramite operatori della pipeline F#.

Nameof sugli operatori

Gli operatori in F# possono essere usati in due modi, come testo dell'operatore stesso o un simbolo che rappresenta il modulo compilato. nameof in un operatore produrrà il nome dell'operatore come dichiarato nell'origine. Per ottenere il nome compilato, usare il nome compilato nell'origine:

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

Nameof nei generics

È anche possibile accettare un nome di un parametro di tipo generico, ma la sintassi è diversa:

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

nameof<'TGeneric> accetta il nome del simbolo come definito nell'origine, non il nome del tipo sostituito in un sito di chiamata.

Il motivo per cui la sintassi è diversa consiste nell'allineare gli altri operatori intrinseci F# come typeof<> e typedefof<>. Ciò rende F# coerente rispetto agli operatori che agiscono su tipi generici e qualsiasi altro elemento nell'origine.

Nameof nei criteri di ricerca

Il nameof modello consente di usare nameof in un'espressione di corrispondenza dei criteri di ricerca come illustrato di seguito:

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 con membri dell'istanza

F# richiede un'istanza di per estrarre il nome di un membro dell'istanza con nameof. Se un'istanza non è facilmente disponibile, è possibile ottenere un'istanza usando 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