Ескертпе
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Жүйеге кіруді немесе каталогтарды өзгертуді байқап көруге болады.
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Каталогтарды өзгертуді байқап көруге болады.
Выражение 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