且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

具有linq表达式的表达式树

更新时间:2021-12-23 21:58:55

这是一个很好的问题.您的两个报价

This is a good question. Your two quotations

Expression<Func<DateTime?, bool>> foo = x => x.HasValue

Func<DateTime?, bool> bar = x => x.HasValue

纯净性的示例:相同的符号(在您的情况下,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.

同渗性使IQueryableIEnumerable看起来如此相似.调用时

Homoiconicity is what makes IQueryable and IEnumerable look so similar. When you invoke

var filteredCollection = myCollection.Where(e => e.IsActive);

实际上,根据filteredCollection的类型,您实际上正在调用具有不同签名的方法(对于IEnumerableFunc<MyClass, bool>,对于IQueryableExpression<Func<MyClass, bool>>).

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);