Reputation: 8791
I have been playing with expression trees this week and I am wondering why this expression produces error when ran.
var pe = Expression.Parameter(typeof(Nullable<DateTime>));
var ex = Expression.Lambda<Func<DateTime?, bool>>(
(Expression<Func<DateTime?, bool>>) (x => x.HasValue), pe);
The idea behind this is to write expression trees with a mix of expression tree api and linq expressions. It would make things easier to write for example instead of calling Expression.Property(...,..)
I would just have x => x.Prop
, right?
In my example instead of this Expression.Property(..hasvalue..)
I would have this: x.HasValue
. It would save me time on writing and it would look shorter, right?
The question is, is this possible?
I guess I might be missing something about
Expression<Func<DateTime?, bool>> foo = x => x.HasValue (this works)
and
Func<DateTime?, bool> bar = x => x.HasValue (this works too)
What is happening behind those two? Are they the same?
Can linq expression be mixed with standard expression tree api???
Please enlighten me on this, I feel lost. :)
Upvotes: 2
Views: 727
Reputation: 12651
This is a good question. Your two quotations
Expression<Func<DateTime?, bool>> foo = x => x.HasValue
and
Func<DateTime?, bool> bar = x => x.HasValue
are examples of homoiconicity: the same symbol (in your case x => x.HasValue) stands for two very different objects. In the first case, it indicates an expression tree; in the second, a function. The former can be compiled down to the latter, but they are different types with different purposes. It is the declaration in your case that tells the compiler which version to go for. In the absence of this context, the compiler cannot read your mind and decides to bail out instead. That's why this won't compile:
var bat = x => x.HasValue;
And that is why your statement won't compile.
Homoiconicity is what makes IQueryable
and IEnumerable
look so similar. When you invoke
var filteredCollection = myCollection.Where(e => e.IsActive);
you are actually calling methods with a different signature depending on the type of filteredCollection
(It's Func<MyClass, bool>
for IEnumerable
and Expression<Func<MyClass, bool>>
for IQueryable
).
Regarding your specific situation, you can't achieve what you want to do directly, but if you write a sneaky extension method:
public static class ExpressionExtensions
{
public static Expression<Func<T, TProperty>> Lambda<T, TProperty>(this ParameterExpression pe, Expression<Func<T, TProperty>> property)
{
return Expression.Lambda<Func<T, TProperty>>(property, pe);
}
}
then you can do this:
var pe = Expression.Parameter(typeof(DateTime?));
var ex = pe.Lambda<DateTime?, bool>(x => x.HasValue);
Upvotes: 1