views:

459

answers:

2

Some Object Relational Mapping (ORM) frameworks (such as LLBLGen) allow you to specify "predicate" parameters to the query methods, such as (simplified a bit):

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

How does that 2nd parameter work syntactically in C#? It kind of looks like a lambda expression, but it doesn't have the parameter part or the "=>". What is it? May need Jon Skeet for this one.

+6  A: 

If you overloaded the ">" operator to return some kind of predicate object on your special "SuperDatabaseMapField" type, you could do such things.

That said, it seems vastly inferior in every way to taking a lambda expression instead (and parsing an expression tree if you have to.)

mquander
Yes, I'm always of the opinion that perverting operators to such an extent usually ends up in confusion, as demonstrated by the OP.
spender
+2  A: 

I agree with mquander's answer. The reason such a construct works is because of the way compilers evaluate expressions. In this case for LLBLGen, the second parameter expects something that can be evaluated to a boolean (for instance).

Operators (+, -, ***, /) are merely expressions that the compiler uses to build syntax trees which it uses to validate if certain combinations of left and right expressions are valid given the context ("+"). For instance a (string literal) + 2.4 (float) is obviously not valid in C#, and the compiler knows this from validating the expressions (string) *(operator_add)* (float).

Therefore, in order to make an odd scenario like the following work:

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

it would be necessary to overload the operators (- and *** and +) to return a new "predicate" object.

Ultimately such a statement would be translated into the following syntax tree (items in "()" are expression types for the purpose of this answer)

(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:     --> >

This is the whole basis on how things like lambda expressions and fluent query works. It all boils down to expression evaluation.

Lambda expressions are more... expressive in that they can touch objects and their fields and properties and methods and allow an arbitrary length syntax tree to be formed.

Mike J