具有linq表达式的表达式树 [英] Expression tree with linq expressions

查看:120
本文介绍了具有linq表达式的表达式树的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这周我一直在玩表达式树,我想知道为什么该表达式在运行时会产生错误.

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

其背后的想法是编写混合了表达式树api和linq表达式的表达式树.例如,这将使编写起来更容易,而不是调用Expression.Property(...,..)我只有x => x.Prop,对吧?

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?

在我的示例中,我将使用以下内容:x.HasValue.这样可以节省我的写作时间,而且看起来更短,对吧?

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?

问题是,这可能吗?

我想我可能会缺少一些有关的东西

I guess I might be missing something about

Expression<Func<DateTime?, bool>> foo = x => x.HasValue (this works)

Func<DateTime?, bool> bar = x => x.HasValue (this works too)

这两个背后发生了什么?他们是一样的吗?

What is happening behind those two? Are they the same?

linq表达式可以与标准表达式树api混合吗?

Can linq expression be mixed with standard expression tree api???

请对此给予启发,我感到失落. :)

Please enlighten me on this, I feel lost. :)

推荐答案

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

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

这篇关于具有linq表达式的表达式树的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆