tags:

views:

184

answers:

2
public Method1(Expression<Func<T, TProperty>> valueToCompare) {
    //Examine expression
}

public Method1(TProperty valueToCompare) : this(x => valueToCompare) {}

and i run them like this

Method1(x => 1);

and

Method1(1);

If i examine the expression when the first overload is called then I get a constant expression. However when I examine the second one I get a member expression.

The question is how do I get access to the value '1' no matter which overload i call.

Update1: I used to do this until I realised the didn't both return the same thing.

if (valueToCompare.Body.NodeType == ExpressionType.Constant)
{
    var constant = valueToCompare.Body as ConstantExpression;
    ValueToCompare = constant != null ? (TProperty)constant.Value : default(TProperty);
}

What will i get if I compile it?

Tried to do this but it didn't work.

if (ValueToCompare .Body.NodeType == ExpressionType.MemberAccess) {
   var member = ValueToCompare .Body as MemberExpression;
   if (member.Expression.NodeType == ExpressionType.Constant)
   {
       ConstantExpression constant = member.Expression as ConstantExpression;
       ValueToCompare = constant.Value;
   }
}

Cheers.

+1  A: 

Are you happy to just compile the expression and run it? That would seem the easiest solution to me...

Alternatively, you could make your overload taking a TProperty explicitly construct a constant expression, rather than using a lambda expression. It really depends on what you're trying to achieve.

As an example of the latter approach, you'd write something like (untested):

public void Method1(TProperty valueToCompare) : this(x => valueToCompare)
{
     Expression constant = Expression.Constant(valueToCompare,
                                               typeof(TProperty));
     ParameterExpression parameter = Expression.Parameter(typeof(T),
                                                          "t");
     Expression lambda = Expression.Lambda<Func<T, TProperty>> (constant,
                                                                parameter);
     Method1(lambda);
}
Jon Skeet
Seems to have worked. Thanks heaps.Also what is the ParameterExpression for and why is it set to "t"?
Schotime
The ParameterExpression is just to represent the parameter for the lambda expression; "t" is just the name. In other words, it's building an expression like (t => 1)
Jon Skeet
Thought it might have been. Cool. Thanks.
Schotime
+1  A: 

The question is how do I get access to the value '1' no matter which overload i call.

You don't, as you've discovered. Not without compiling and executing the expression tree to produce its value.

Remember, the purpose of an expression tree is to capture the compile-time information about the expression and present it at runtime, not the runtime value that evaluating the expression produces.

In your example, you have two different expressions -- one is a constant, one is an outer variable of a closure. Outer variables are represented by fields, so you get a field access expression. The expression tree you get represents the expression that you put in the lambda.

Perhaps you can describe what you are really trying to do; there is probably a better way. If what you want is the value, why do you need an expression tree at all?

Eric Lippert