我可以定义一个引用表达式参数,这样不仅表达式的结果类型是编译时检查的 还有呼叫站点表达。
让我们看一个例子:
type A = {
a : int
}
type Checker () =
static member Check(e : Expr<int>) : ResultType = ...
以下明显的类型检查
let a = { a = 1 }
Checker.Check <@ a.a @>
导致类似于PropertyGet( ..., PropertyGet (....), a)
的实际表达式。
现在还有其他方式
let getInt (a:A) : int = a.a
以下也编译
Checker.Check <@ getInt a @>
但是,如何防止第二个示例编译并仅允许PropertyGet
s? (仅作为一个例子)
我知道我可以在运行时检查表达式的结构 - 但我喜欢进行编译时检查。
答案 0 :(得分:1)
正如Fyodor在评论中所说,没有办法确保报价在编译时只是某种形状。这是非常不幸的,但所有基于引用(或基于表达式)的库都受此影响(最明显的是LINQ),如果您的需求是“仅属性 - 获取者”,那么我想您可以将其作为运行时检查
如果我真的想保证这一点,我可能会尝试使用F# Compiler Service,这样可以获得typed expression tree。然后,您可以遍历树并查找项目中的所有引用并报告错误(它可以以一些可扩展的方式作为linter插件完成,其他人也可以从中受益)。
如果您进入DSL方向,那么您可以编写a |> get "foo" |> get "bar"
(使用管道)或a?foo?bar
(使用?
运算符),但之后会丢失检查在名称上,这似乎比不能检查报价的正确形状更糟糕。