您的第二个委托不是以匿名委托(而不是 lambda)格式重写第一个委托。看你的条件了。
First:
x.ID == packageId || x.Parent.ID == packageId || x.Parent.Parent.ID == packageId
Second:
(x.ID == packageId) || (x.Parent != null && x.Parent.ID == packageId) ||
(x.Parent != null && x.Parent.Parent != null && x.Parent.Parent.ID == packageId)
对 lambda 的调用将引发任何异常x
其中 ID 不匹配且父级为 null 或不匹配且祖父母为 null。将 null 检查复制到 lambda 中,它应该可以正常工作。
对问题发表评论后编辑
如果你的原始对象不是List<T>
,那么我们无法知道返回类型是什么FindAll()
是,以及这是否实现了IQueryable
界面。如果确实如此,那么这可能可以解释这种差异。因为 lambda 可以在编译时转换为Expression<Func<T>>
但匿名代表不能,那么您可能正在使用的实现IQueryable
使用 lambda 版本时,但使用匿名委托版本时使用 LINQ-to-Objects。
这也可以解释为什么你的 lambda 没有引起NullReferenceException
。如果您要将 lambda 表达式传递给实现IEnumerable<T>
but not IQueryable<T>
, lambda 的运行时求值(与其他方法没有什么不同,无论是否匿名)都会抛出NullReferenceException
当它第一次遇到一个物体时ID
不等于目标并且父母或祖父母为空。
添加于 2011 年 3 月 16 日上午 8:29(美国东部时间)
考虑以下简单示例:
IQueryable<MyObject> source = ...; // some object that implements IQueryable<MyObject>
var anonymousMethod = source.Where(delegate(MyObject o) { return o.Name == "Adam"; });
var expressionLambda = source.Where(o => o.Name == "Adam");
这两种方法产生完全不同的结果。
第一个查询是简单版本。匿名方法产生一个委托,然后将其传递给IEnumerable<MyObject>.Where
扩展方法,其中的全部内容source
将针对您的委托进行检查(使用普通编译代码在内存中手动检查)。换句话说,如果您熟悉 C# 中的迭代器块,则类似于执行以下操作:
public IEnumerable<MyObject> MyWhere(IEnumerable<MyObject> dataSource, Func<MyObject, bool> predicate)
{
foreach(MyObject item in dataSource)
{
if(predicate(item)) yield return item;
}
}
这里的重点是您实际上正在执行过滤在记忆中在客户端。例如,如果您的源是一些 SQL ORM,则不会有WHERE
查询中的子句;整个结果集将被带回客户端并进行过滤there.
第二个查询使用 lambda 表达式,被转换为Expression<Func<MyObject, bool>>
并使用IQueryable<MyObject>.Where()
扩展方法。这会产生一个对象,其类型也为IQueryable<MyObject>
。所有这些都在通过之后起作用表达到底层提供商。这就是为什么你没有得到NullReferenceException
。这完全取决于查询提供者如何翻译表达式(它不是一个可以调用的实际编译函数,而是一个表达式的表示)logic使用对象的表达式)转换为它可以使用的东西。
一个简单的方法来了解区别(或者,至少,有is)一个区别,就是调用AsEnumerable()
在您致电之前Where
在 lambda 版本中。这将强制您的代码使用 LINQ-to-Objects(意味着它在IEnumerable<T>
就像匿名委托版本一样,而不是IQueryable<T>
就像当前的 lambda 版本一样),并且您将得到预期的异常。
TL;DR 版本
简而言之,您的 lambda 表达式正在被转换为针对您的数据源的某种查询,而匿名方法版本正在评估entire内存中的数据源。无论将 lambda 转换为查询,所做的任何操作都不代表您期望的逻辑,这就是为什么它不会产生您期望的结果。