Nameof
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>
将采用源中定义的符号名称,而不是在调用站点替换的类型名称。
语法不同的原因是与 typeof<>
和 typedefof<>
等其他 F# 内部运算符对齐。 这使得 F# 与作用于泛型类型和源中的任何其他内容的运算符保持一致。
模式匹配中的 Nameof
nameof
模式 允许你在模式匹配表达式中使用 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
F# 需要一个实例才能使用 nameof
提取实例成员的名称。 如果实例不容易获得,则可以使用 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