Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Uttrycket nameof skapar en strängkonstant som matchar namnet i källan för nästan alla F#-konstruktioner i källan.
Syntax
nameof symbol
nameof<'TGeneric>
Anmärkningar
nameof fungerar genom att matcha symbolen som skickas till den och skapar namnet på symbolen som den deklareras i källkoden. Detta är användbart i olika scenarier, till exempel loggning, och skyddar din loggning mot ändringar i källkoden.
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)
Den sista raden genererar ett undantag och "month" visas i felmeddelandet.
Du kan ta ett namn på nästan alla F#-konstruktioner:
module M =
let f x = nameof x
printfn $"{(M.f 12)}"
printfn $"{(nameof M)}"
printfn $"{(nameof M.f)}"
nameof är inte en förstklassig funktion och kan inte användas som sådan. Det innebär att den inte kan tillämpas delvis och att värden inte kan skickas till den via F#-pipelineoperatorer.
Namn på operatorer
Operatorer i F# kan användas på två sätt, som själva operatortexten eller en symbol som representerar det kompilerade formuläret.
nameof på en operator kommer att producera namnet på operatorn som den deklareras i källan. Om du vill hämta det kompilerade namnet använder du det kompilerade namnet i källan:
nameof(+) // "+"
nameof op_Addition // "op_Addition"
Namn på generiska
Du kan också ta ett namn på en allmän typparameter, men syntaxen är annorlunda:
let f<'a> () = nameof<'a>
f() // "a"
nameof<'TGeneric> kommer att ta namnet på symbolen enligt definitionen i källan, inte namnet på den typ som ersätts på en samtalswebbplats.
Anledningen till att syntaxen är annorlunda är att anpassa till andra F#-inbyggda operatorer som typeof<> och typedefof<>. Detta gör F# konsekvent med avseende på operatorer som agerar på generiska typer och allt annat i källan.
Namn på i mönstermatchning
Med nameof mönstret kan du använda nameof i ett mönstermatchningsuttryck. Detta är särskilt användbart när du matchar strängvärden mot namnen på symboler i koden, vilket ger kompileringstidssäkerhet och automatiska uppdateringar när du omstrukturerar.
Ett praktiskt exempel är att deserialisera händelser eller meddelanden där strängvärden representerar typ- eller skiftlägesnamn:
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
Att använda nameof i stället för strängliteraler som "OrderCreated" ger flera fördelar:
- Om du byter namn på ett diskrimineringsärende uppdateras mönstret automatiskt.
- Kompilatorn förhindrar stavfel genom att se till att symbolen finns.
- Koden förblir konsekvent under refaktorisering.
Du kan också använda nameof med parametrar:
let f (str: string) =
match str with
| nameof str -> "It's 'str'!"
| _ -> "It is not 'str'!"
f "str" // matches
f "asdf" // does not match
Namn på med instansmedlemmar
F# kräver en instans för att extrahera namnet på en instansmedlem med nameof. Om en instans inte är lätt tillgänglig kan du hämta en med hjälp av 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