F#中是否有类似于C#的nameof(..)的等效功能?

19

我有以下几行代码,我想从C#转换到F#:

private const string TypeName = nameof(MyClass);
private const string MemberName = nameof(MyClass.MyMember);

TypeName的值是"MyClass"MemberName的值是"MyMember"。我需要在F#中写什么?


8
看起来它仍在实施中 - F# RFC FS-1003 - nameof Operator。另请参阅讨论线程 - SpruceMoose
1
nameof 是一个预览功能,从 F# 4.7 开始提供。 - Cosmin Sontu
1个回答

22

从F# 4.7开始,有一个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)

正如评论中提到的那样,一个适当的nameof操作符正在开发中。

与此同时,您可以使用F#引用(类似于C#表达式树)来实现类似的功能——它略微丑陋,并且需要一些纪律(您需要在引用中放入实际成员访问),但至少它检查了成员是否存在并防止了拼写错误:

open Microsoft.FSharp.Quotations

let nameof (q:Expr<_>) = 
  match q with 
  | Patterns.Let(_, _, DerivedPatterns.Lambdas(_, Patterns.Call(_, mi, _))) -> mi.Name
  | Patterns.PropertyGet(_, mi, _) -> mi.Name
  | DerivedPatterns.Lambdas(_, Patterns.Call(_, mi, _)) -> mi.Name
  | _ -> failwith "Unexpected format"

let any<'R> : 'R = failwith "!"
< p > any 定义只是一个通用值,您可以使用它来引用实例成员:
nameof <@ any<System.Random>.Next @>
nameof <@ System.Char.IsControl @>

那看起来是一个真正的方法,但我认为我必须等待nameof运算符被实现,因为我需要结果作为编译时常量(想将其用作属性的参数)。此外,我是否正确地理解,我只能获取成员的名称,而不能获取类型的名称? - David
4
@David - 你说得对,这不是编译时常量,你只能获取成员名称(对于类型名称,你可能只需要 typeof<System.Random>.Name,但这与C#中的相同 - 如果有 nameof 将更好!) - Tomas Petricek
@TomasPetricek 请查看 https://dev59.com/pr7pa4cB1Zd3GeqPynD0 - Franco Tiveron

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接