3

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

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

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

4

2 回答 2

6

如果你重载了 " >" 操作符以在你的特殊 " " 类型上返回某种谓词对象SuperDatabaseMapField,你可以做这样的事情。

也就是说,它似乎在各个方面都比采用 lambda 表达式(如果需要,还可以解析表达式树)。

于 2009-08-10T21:30:08.663 回答
2

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

运算符(+、-、***、/)只是编译器用来构建语法树的表达式,它用于验证给定上下文(“+”)的左右表达式的某些组合是否有效。例如a(string literal) + 2.4(float) 在 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 表达式更具...表现力,因为它们可以触及对象及其字段、属性和方法,并允许形成任意长度的语法树。

于 2009-08-10T21:57:27.250 回答