一些对象关系映射 (ORM) 框架(例如 LLBLGen)允许您为查询方法指定“谓词”参数,例如(简化一点):
var entities = adapter.FetchEntities(EntityType.Employee,
EmployeeFields.Salary > 50000);
在 C# 中,第二个参数在语法上是如何工作的?它有点像 lambda 表达式,但它没有参数部分或“=>”。它是什么?这个可能需要 Jon Skeet。
一些对象关系映射 (ORM) 框架(例如 LLBLGen)允许您为查询方法指定“谓词”参数,例如(简化一点):
var entities = adapter.FetchEntities(EntityType.Employee,
EmployeeFields.Salary > 50000);
在 C# 中,第二个参数在语法上是如何工作的?它有点像 lambda 表达式,但它没有参数部分或“=>”。它是什么?这个可能需要 Jon Skeet。
如果你重载了 " >
" 操作符以在你的特殊 " " 类型上返回某种谓词对象SuperDatabaseMapField
,你可以做这样的事情。
也就是说,它似乎在各个方面都比采用 lambda 表达式(如果需要,还可以解析表达式树)。
我同意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 表达式更具...表现力,因为它们可以触及对象及其字段、属性和方法,并允许形成任意长度的语法树。