以下两种方法是否有区别?我得到的输出是相同的,但是我试图了解哪种是正确和有效的
方法1:
Product product12 = products.Where(p => p.ProductID == 12).First();
方法2:
Product prod12 = products.First(p => p.ProductID == 12);
((我假设您正在使用Linq to .Net)首先,让我们看一下它们的源代码:
这里是Where()
:
Where()
这里是public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
if (source == null)
throw Error.ArgumentNull("source");
if (predicate == null)
throw Error.ArgumentNull("predicate");
if (source is Iterator<TSource>)
return ((Iterator<TSource>)source).Where(predicate);
if (source is TSource[])
return new WhereArrayIterator<TSource>((TSource[])source, predicate);
if (source is List<TSource>)
return new WhereListIterator<TSource>((List<TSource>)source, predicate);
return new WhereEnumerableIterator<TSource>(source, predicate);
}
First()
并且让我们找到每个代码的作用:
First()
基于 public static TSource First<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) {
if (source == null) throw Error.ArgumentNull("source");
if (predicate == null) throw Error.ArgumentNull("predicate");
foreach (TSource element in source) {
if (predicate(element)) return element;
}
throw Error.NoMatch();
}
的源代码,我们可以说,products.First(p => p.ProductID == 12);
将遍历集合,并且在找到符合条件的集合中的第一个项目时将停止迭代。
First()
首先,它将在元素满足条件的First()
方法中创建迭代器。然后,它将再次向该迭代器添加第一个元素。并且,再次[[一旦找到第一个元素,它将立即对其进行粉碎。
延迟执行。它与您的问题的结果有关。
延迟执行是执行模型的一种模式,通过该模式CLR确保仅在需要时才提取值基于IEnumerable的信息源。当任何Linq运算符使用延迟执行,CLR封装相关的信息,例如原始序列,谓词或选择器(如果任何),放入一个迭代器中,该迭代器将在信息为使用ToList方法从原始序列中提取或ForEach方法或手动使用基础的GetEnumerator和C#中的MoveNext方法。
而且,问题是。
哪个更快?
要点是,products.Where(p => p.ProductID == 12).First();
比Where
快。如果是Where().First
和First
。否则,List
将更快。 Array
。
First()
的实现。如果您的集合是列表,它将返回Here is the detailed exlpanation in @Akash Kava answer,但是Where()
只会在源上进行迭代。在我看来,它们在WhereListIterator()
的First()
中有所提高。在此之后,我们将调用implementation方法,该方法不使用谓词作为输入,仅对已过滤的集合进行迭代。而且,据我所知,
WhereListIterator
迭代器避免了间接虚拟表调用,而是直接调用迭代器方法。
First()
]上查看结果>正确的答案是,更快的速度取决于所应用的过滤器的类型和被迭代的集合的类型。
Where
所以没有明确的答案。
[另一个测试,https://dotnetfiddle.net/3lCqsR一直都在,First快于Where First。
UPDATE
分析List类后,发现Where()。First()仅比First()快,仅对于List和Array,它不适用于IQueryable或任何其他形式的Enumerable。原因是,列表中使用的枚举器未按线程缓存。 List总是创建新的Enumerator,因此First()使用List的Enumerator(迭代器)。WhereListIterator用于List的Where()中,不会创建新的Enumerator,而是将当前Iterator缓存在线程中。这使Where()。First()运行得更快。
但是,此缓存WhereListIterator的操作会花费一些成本,因此,对于较小的集合和某些产生较小结果的条件,Where()。First()较慢。
如果您查看此示例,“ First每次都击败First”。
Func<Item,bool> filter = x => x.Size == 200;
Run("First", () => items.First( filter ));
Run("Where First", () => items.Where( filter ).First());
88 milliseconds for First
69 milliseconds for Where First
filter = x => x.Size < 200;
Run("First", () => items.First( filter ));
Run("Where First", () => items.Where( filter ).First());
2 milliseconds for First
4 milliseconds for Where First
filter = x => x.Size > 200;
Run("First", () => items.First( filter ));
Run("Where First", () => items.Where( filter ).First());
88 milliseconds for First
71 milliseconds for Where First