VB编译器自动将lambda转换为LambdaExpression
等价物(例如Dim a As LambdaExpression = Function(x) x.Length
)。直到最近,我还认为仅功能应用于lambdas,但后来我尝试将方法调用的结果作为参数传递给方法时发现了相同的行为。编译器将我的调用转换为MethodCallExpression
而不是拨打电话!
Dim myQuery = From x In DataSource.Items
Group By x.Key Into g = Group
Select New With {
.Key = Key,
.RedItems = g.Sum(ItemsOfColor(Colors.Red))
}
Private Function ItemsOfColor(color As Integer) As Expression(Of Func(Of Item, Integer))
Return Function(item) If(item.Color = color, 1, 0)
End Function
RedItems
包含一个MethodCallExpression
来调用ItemsOfColor
Colors.Red
作为参数,而不是LambdaExpression
结果我预期的ItemsOfColor
电话。
问题:为什么编译器认为这是我想要的行为,是否有任何方法可以将其关闭?
答案 0 :(得分:0)
我想我终于明白了这个问题...所以这里有。查询表达式语法(如上所示)使显示 .RedItems = g.Sum(ItemsOfColor(Colors.Red))
是正常的方法调用,但它不是。那个“调用”实际上位于前一行Select
语句的lambda体内。用lambda语法重写,这将是:
.Select(Function(x) New With {
.Key = Key,
.RedItems = g.Sum(ItemsOfColor(Colors.Red))
})
这清楚地突出显示我们实际上已经内部一个lambda。负责将lambda参数转换为Select
到表达式树的编译步骤会看到对ItemsOfColor
的调用,并创建一个MethodCallExpression
,就像我们期望的那样!
简而言之,将方法调用转换为表达式没有特殊规则,它实际上是一个lambda,而我在EF / LINQ当前版本中的原始问题是不可能的。也许有一天,MS会扩展两个中的一个来识别MethodCallExpression
,它会产生一个表达式并进行调用(从而使这种类型的重构成为可能)。