c# - Linq 表达式语法和编译

标签 c# linq expression

我正在查找一个示例,了解如何使用 Telerik 网格框架的特定部分(ASP.NET MVC3,但这与此处无关)。他们有一大段代码,它接受过滤器描述列表并构建一个表达式:

System.Linq.Expressions.Expression<Func<MyModel, bool> exp = 
               ExpressionBuilder.Expression<MyModel>(listOfFilters);

好的,所以我认为这很好。 Expression 包装了一个 lambda,它在 MyModel 上运行以产生一个 bool。伟大的。现在,他们的示例只是将其放入 Where 中,如下所示:

someList = someList.Where(exp);

我假设应该是“嘿,将该表达式应用于列表中的所有项目(这当然也是通用的 MyModel )。但是,VS 声称代码无法编译。我得到“没有重载存在或System.Func 有一些无效参数。

我试了一下,发现我可以编译表达式,这给出了更难看的样子

someList = someList.Where(x => exp.Compile()(x));

它确实可以编译并且可能会工作,但这让我感到不舒服,因为我现在显然在我所知道的范围之外操作。

是否有某些原因(IDE 设置、标记、过时的文档)示例的方法不起作用? 我的 hack 和示例有粗略的等效性吗? 我是否应该以不同的方式构建 hack 以避免一些可怕的问题(例如,它不会每次检查列表中的项目时都编译表达式,对吗?我认为它足够聪明吗?)

-- 编辑 是的,它是 IEnumerable。我陷入了“所有地方都是平等的”陷阱。 谢谢大家!

最佳答案

Where() 有两个版本方法:一个操作IEnumerable<T>并采取 Func<T, bool> , 另一个在 IQueryable<T> 上工作并采取 Expression<Func<T, bool>> .原因是IQueryable<T>可以表示一些远程数据,如数据库表。当您查询表格时,您不希望仅仅为了找到您要查找的单个项目而传输整个表格。

这就是为什么有 Expression 的原因:它用于表示一些代码,但以一种可以轻松处理的方式,例如转换为 SQL。或者您可以将其编译为普通 IL 代码并从中生成委托(delegate)。

如果你想在一个普通的内存列表上操作(实现了 IEnumerable<T> ,但不是 IQueryable<T> ),你根本不需要表达式,你可以一直使用委托(delegate),你的代码将可能更简单、更快。

但是如果你想使用 Expression s,你可以,正如你发现的那样。有几个选项:

  1. 使用 the AsQueryable() method .这样,您将获得类似 Where() 的方法与 Expression 一起工作

    someList.AsQueryable().Where(exp)
    
  2. 通过调用 the Compile() method 编译表达式.它返回一个委托(delegate),您可以将其直接传递给 Where() .

    someList.Where(exp.Compile())
    

您的尝试实际上会为集合中的每个项目编译表达式,因此它的性能可能很差。

关于c# - Linq 表达式语法和编译,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9472314/

相关文章:

c# - 如何在 SQL 查询中包含数组的所有元素?

c# - 参数类型 System.Linq.IQueryable<> 不可分配给参数类型 Systems.collection.generic.ienumerable

.net - 如何在 LINQ to SQL 中编写此 T-SQL?

c# - 如何在表达式树 C# 中使用隐式转换?

c# - 如何使用签名版本 4 生成 AWS S3 预签名 URL

c# - 包含异常作为 DataContractSerializer WCF C# 的 DataMember

c# - 在多线程C#应用程序中使用互操作的Excel文件操作失败

c# - 由于其保护级别而无法访问结构

c++ - 为什么以下 while 循环使用 AND 而不是 OR

reporting-services - Reporting Services 从表达式中的 DateTime 中删除时间