【问题标题】:F# nameof operator not a first-class functionF# nameof 运算符不是一等函数
【发布时间】:2020-11-10 02:37:32
【问题描述】:

我在我的项目文件中使用带有 <LangVersion>preview</LangVersion> 的 F# 4.7。

我有一个这样的类型:

type Record = {
  Name : string
  Description : string
  FieldNotInterestedIn: int
}

我想以类型安全的方式获取某些字段的名称,但不是全部。我知道我可以使用反射获取所有字段名称。

这是我想出的最简洁的代码。能不能再简洁点?

let certainFieldNames =
  let r = Unchecked.defaultof<Record>
  
  [
    nameof r.Name
    nameof r.Description
  ]

【问题讨论】:

  • 我不确定我是否明白这个问题 - 你是在问你是否可以做 [r.Name; r.Description] |&gt; List.map nameof 吗?那是行不通的,因为nameof 是一个特殊的运算符,而不是一个普通的函数......
  • 我先试了一下,想知道为什么nameof 故意不是一流的函数。
  • 我也想知道我是否可以在不创建值的实例的情况下做到这一点,就像我使用 Unchecked.defaultof&lt;Record&gt; 所做的那样。
  • 最好能做类似nameof Record.Name的事情。
  • @brett,你可以这样做,使用 defaultof 是首选方式,因为它会被删除。此外,即使没有,该函数也永远不会创建引用类型的实例。

标签: reflection properties f# nameof


【解决方案1】:

特殊函数nameof 是一个编译时特性,它返回标识符的静态名称。因此,它不能在运行时使用,您的运行时代码不会包含对函数的任何引用,结果始终是编译时常量。

因此,您不能将它与管道一起使用,也不能作为一流的功能使用。当你尝试它时,你会得到给定的错误。

您编写的代码是最简洁的,因为您似乎想要获取这些标识符的名称。没有语法方法可以动态地执行此操作(除了反射,但这是一种完全不同的方法)。

添加此特殊函数/运算符的主要原因是帮助重命名代码中的操作,或者在ArgumentNullException 等异常中安全地使用参数名称。

完整的详细信息在 RFC 中,特别是“其他注意事项”部分,其中详细说明了您的用例:https://github.com/fsharp/fslang-design/blob/master/preview/FS-1003-nameof-operator.md

在实现中,就不需要使用Unchecked.defaultof 进行了长时间的讨论,但是如果不对解析器进行重大重写,我们就找不到这样做的好方法。请注意,该代码不会增加运行时开销,它会被删除。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-29
  • 2019-07-06
  • 1970-01-01
  • 2019-06-17
  • 1970-01-01
  • 2016-08-15
相关资源
最近更新 更多