Partilhar via


Nome da

A nameof expressão produz uma constante de cadeia de caracteres que corresponde ao nome na origem para praticamente qualquer construção F# na origem.

Sintaxe

nameof symbol
nameof<'TGeneric>

Observações

nameof funciona resolvendo o símbolo passado para ele e produz o nome desse símbolo como ele é declarado em seu código-fonte. Isso é útil em vários cenários, como o registro em log, e protege seu registro contra alterações no código-fonte.

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)

A última linha lançará uma exceção e "month" será mostrada na mensagem de erro.

Você pode usar um nome de quase todas as construções F#:

module M =
    let f x = nameof x

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

nameof não é uma função de primeira classe e não pode ser usada como tal. Isso significa que ele não pode ser parcialmente aplicado e os valores não podem ser canalizados para ele por meio de operadores de pipeline F#.

Nome dos operadores

Os operadores em F# podem ser usados de duas maneiras, como um texto de operador em si ou um símbolo que representa a forma compilada. nameof em um operador produzirá o nome do operador tal como é declarado na fonte. Para obter o nome compilado, use o nome compilado na fonte:

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

Nome dos genéricos

Você também pode usar um nome de um parâmetro de tipo genérico, mas a sintaxe é diferente:

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

nameof<'TGeneric> tomará o nome do símbolo conforme definido na fonte, não o nome do tipo substituído em um site de chamada.

A razão pela qual a sintaxe é diferente é alinhar com outros operadores intrínsecos do F# como typeof<> e typedefof<>. Isso torna o F# consistente em relação aos operadores que atuam em tipos genéricos e qualquer outra coisa na fonte.

Nome de na correspondência de padrões

O nameof padrão permite que você use nameof em uma expressão de correspondência de padrão. Isso é particularmente útil ao comparar valores de cadeia de caracteres com os nomes de símbolos em seu código, fornecendo segurança em tempo de compilação e atualizações automáticas quando você refatora.

Um exemplo prático é a desserialização de eventos ou mensagens em que os valores de cadeia de caracteres representam nomes de tipo ou caso:

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

Usar nameof em vez de literais de cadeia de caracteres como "OrderCreated" fornece vários benefícios:

  • Se você renomear um caso de união discriminada, o padrão será atualizado automaticamente.
  • O compilador evita erros de digitação garantindo que o símbolo exista.
  • Seu código permanece consistente durante a refatoração.

Você também pode usar nameof com parâmetros:

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

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

Nome de com membros da instância

F# requer uma instância para extrair o nome de um membro da instância com nameof. Se uma instância não estiver facilmente disponível, então uma pode ser obtida 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