我要从C#移植到F#的以下代码行:

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

那么TypeName的值就是"MyClass",然后MemberName的值就是"MyMember"。我必须用F#写什么?

最佳答案

从F#4.7开始,有一个 nameof operator:

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 "!"
any定义只是一个通用值,可用于引用实例成员:
nameof <@ any<System.Random>.Next @>
nameof <@ System.Char.IsControl @>

10-08 14:31