谓词参数如何在C#语法上工作?

时间:2009-08-10 21:26:55

标签: c# syntax lambda orm llblgenpro

某些对象关系映射(ORM)框架(如LLBLGen)允许您为查询方法指定“谓词”参数,例如(简化一点):

var entities = adapter.FetchEntities(EntityType.Employee,
    EmployeeFields.Salary > 50000);

第二个参数如何在C#语法上起作用?它看起来像一个lambda表达式,但它没有参数部分或“=>”。它是什么?可能需要Jon Skeet这个。

2 个答案:

答案 0 :(得分:6)

如果您重载“>”运算符以在特殊的“SuperDatabaseMapField”类型上返回某种谓词对象,则可以执行此类操作。

那就是说,取代lambda表达式(并且如果必须解析表达式树)在各方面看起来都差得多。

答案 1 :(得分:2)

我同意mquander's回答。这样的构造工作的原因是因为编译器评估表达式的方式。在这种情况下,对于LLBLGen,第二个参数需要一些可以计算为布尔值的东西(例如)。

运算符(+, - ,***,/)只是编译器用于构建语法树的表达式,它用于验证左侧和右侧表达式的某些组合在给定上下文(“+”)时是否有效。例如a(字符串文字)+ 2.4(浮点数)显然在C#中无效,编译器通过验证表达式(string) 来了解这一点( operator_add) (float)

因此,为了做出如下工作的奇怪场景:

FetchEntities(EntityType.Employee, 
    EmployeeFields.Salary > ((EmployeeFields.DateOfBirth - 10) * 1.2) + 1024)

有必要重载运算符( - 和***和+)以返回一个新的“谓词”对象。

最终这样的语句将被翻译成以下语法树(“()”中的项目是用于此答案的表达式类型)

(BinaryComparison)
    LeftSide: (Field_Reference)    --> EmployeeFields.Salary
    RightSide:
        (MathematicOperator)
            LeftSide:
                (MathematicOperator)
                    LeftSide: 
                        (MathematicOperator)
                            LeftSide: (Field_Reference)    --> EmployeeFields.DateOfBirth
                            RightSide: (constant)    --> 10
                            Operator:      --> -
                    RightSide: (constant)    --> 1.2
                    Operator:     --> ***
            RightSide: (constant)    --> 1024
            Operator:     --> +
    Operator:     --> >

这是关于lambda表达式和流畅查询的工作原理的全部基础。这一切都归结为表达评估。

Lambda表达式更具有表现力,因为它们可以触摸对象及其字段,属性和方法,并允许形成任意长度的语法树。