这是可以在 C# 中完成的操作 -
var two = 2;
System.Linq.Expressions.Expression<System.Func<int, int>> expr = x => x * two;
expr.Compile().Invoke(4); // returns 8
我希望在 F# 中做同样的事情。这是我尝试过的,但没有编译 -
let two = 2
let expr = (fun x -> x * two) : System.Linq.Expressions.Expression<System.Func<int, int>>
expr.Compile().Invoke(4) // desired to return 8
也许可以预见,第 2 行编译失败并出现以下错误 -
"This function takes too many arguments, or is used in a context where a function is not expected."
let expr = (fun x -> x * two) : System.Linq.Expressions.Expression<System.Func<int, int>>
^^^^^^^^^^^^^^^^
最佳答案
我不确定您为什么要避免使用 F# 引号 - 在表面上,它们与 C# 表达式树几乎相同,如果您想在 F# 中创建表达式树,编译器将使用引号无论如何都在掩护下......
无论如何,您可以在不显式写出 <@ .. @>
的情况下执行此操作因为当函数作为参数传递给方法时,编译器可以自动引用函数。所以你可以这样做:
type Expr =
static member Quote(e:Expression<System.Func<int, int>>) = e
let two = 2
let expr = Expr.Quote(fun x -> x * two)
expr.Compile().Invoke(4) // desired to return 8
编辑:但是,这实际上编译为一个 F# 引号,包裹在一个将其转换为 C# 表达式树的调用中。所以,最后,你会得到和你写的一样的东西:
open Microsoft.FSharp.Linq.RuntimeHelpers
let two = 2
let expr =
<@ System.Func<_, _>(fun x -> x * two) @>
|> LeafExpressionConverter.QuotationToExpression
|> unbox<Expression<Func<int, int>>>
expr.Compile().Invoke(4) // desired to return 8
关于c# - 如何使用 F# lambda 创建 Linq 表达式树?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23146473/