C# 如何使用F#lambda创建Linq表达式树?

C# 如何使用F#lambda创建Linq表达式树?,c#,linq,f#,expression-trees,C#,Linq,F#,Expression Trees,以下是在C#中可以做的事情- var-two=2; System.Linq.Expressions.Expression expr=x=>x*two; expr.Compile().Invoke(4);//返回8 我想用F#做精确的等价。下面是我尝试过的,但没有编译- let two = 2 let expr = (fun x -> x * two) : System.Linq.Expressions.Expression<System.Func<int, int>&g

以下是在C#中可以做的事情-

var-two=2;
System.Linq.Expressions.Expression expr=x=>x*two;
expr.Compile().Invoke(4);//返回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
让expr=(funx->x*two):System.Linq.Expressions.Expression
expr.Compile().Invoke(4)//希望返回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>>
            ^^^^^^^^^^^^^^^^
“此函数接受的参数太多,或者在不需要函数的上下文中使用。”
让expr=(funx->x*two):System.Linq.Expressions.Expression
^^^^^^^^^^^^^^^^

我不知道你为什么要避免使用F#引号-在封面下,它们与C#表达式树几乎是一样的,如果你想在F#中创建表达式树,编译器在任何情况下都会在封面下使用引号

无论如何,您可以在不编写显式
的情况下执行此操作,因为当函数作为参数传递给方法时,编译器可以自动引用函数。因此,您可以:

type Expr=
静态成员引号(e:表达式)=e
让2=2
让expr=expr.Quote(乐趣x->x*two)
expr.Compile().Invoke(4)//希望返回8
EDIT:然而,这实际上会编译成一个F#引号,封装在一个调用中,将其转换为C#表达式树。所以,最后,你会得到同样的东西,就像你写的:

打开Microsoft.FSharp.Linq.RuntimeHelpers
让2=2
设expr=
x*2)@>
|>LeafExpressionConverter.QuotationToExpression
|>拆开
expr.Compile().Invoke(4)//希望返回8

谢谢您的回答!这很好,虽然这似乎是一个非常小的工作:)但是,为了回答你的问题-我想避免使用代码引用,因为它们不允许从词汇环境中捕获变量(例如
two
变量)。但是,如果这是错误的,请纠正我!在这两种情况下,它的行为相同。局部
let
绑定变量不被引号捕获-它只包含变量的值。模块公开的公共变量将被捕获为引用(属性getter)。后续编辑-如果表达式树本身变异了从其周围上下文中提取的引用,那么这将不起预期的作用吗?我打算使用它的一些lambda可能会改变更广泛的程序状态。这是不允许的
mutable
变量-例如,下面给出了一个错误
let mutable two=2 in 1)F#引号不能直接调用-因此您必须将其转换为C#表达式树并调用它。2) 它将比普通的F#慢,因为转换到表达式树会增加一些开销。我不知道准确的数字是多少——我没有做任何测量。3) 不确定-取决于C#expression eval是否可用。
"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>>
            ^^^^^^^^^^^^^^^^