Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Выражение 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# можно использовать двумя способами, как сам текст оператора или символ, представляющий скомпилированную форму.
nameof в операторе будет производиться имя оператора, как оно объявляется в источнике. Чтобы получить скомпилированное имя, используйте скомпилированное имя в источнике:
nameof(+) // "+"
nameof op_Addition // "op_Addition"
Nameof для универсальных шаблонов
Вы также можете использовать имя параметра универсального типа, но синтаксис отличается:
let f<'a> () = nameof<'a>
f() // "a"
nameof<'TGeneric> будет принимать имя символа, как определено в источнике, а не имя типа, заменяемого на сайте вызова.
Причина, по которой синтаксис отличается, заключается в выравнивании с другими встроенными операторами F#, например typeof<> и typedefof<>. Это делает 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
Использование nameof вместо строковых литерал, например "OrderCreated" , обеспечивает несколько преимуществ:
- Если переименовывать дискриминируемый случай объединения, шаблон автоматически обновляется.
- Компилятор предотвращает опечатки, гарантируя наличие символа.
- Код остается согласованным во время рефакторинга.
Можно также использовать 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 с элементами экземпляра
Для извлечения имени члена nameofэкземпляра с помощью F# требуется экземпляр. Если экземпляр недоступен, его можно получить с помощью 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