使用LINQ where(lamdaexp).First and First(lambdaexp)

问题描述 投票:3回答:4

以下两种方法是否有区别?我得到的输出是相同的,但是我试图了解哪种是正确和有效的

方法1:

Product product12 = products.Where(p => p.ProductID == 12).First();

方法2:

Product prod12 = products.First(p => p.ProductID == 12);
c# linq lambda
4个回答
7
投票

((我假设您正在使用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()

并且让我们找到每个代码的作用:

  1. 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);将遍历集合,并且在找到符合条件的集合中的第一个项目时将停止迭代。

  1. First()

首先,它将在元素满足条件的First()方法中创建迭代器。然后,它将再次向该迭代器添加第一个元素。并且,再次[[一旦找到第一个元素,它将立即对其进行粉碎

作为补充说明,LINQ在某些方法中使用

延迟执行。它与您的问题的结果有关。

延迟执行是执行模型的一种模式,通过该模式CLR确保仅在需要时才提取值基于IEnumerable的信息源。当任何Linq运算符使用延迟执行,CLR封装相关的信息,例如原始序列,谓词或选择器(如果任何),放入一个迭代器中,该迭代器将在信息为使用ToList方法从原始序列中提取或ForEach方法或手动使用基础的GetEnumerator和C#中的MoveNext方法。

而且,问题是。

哪个更快?


要点是,products.Where(p => p.ProductID == 12).First();Where快。如果是Where().FirstFirst。否则,List将更快。 Array

让我们注意First()的实现。如果您的集合是列表,它将返回Here is the detailed exlpanation in @Akash Kava answer,但是Where()只会在源上进行迭代。在我看来,它们在WhereListIterator()First()中有所提高。在此之后,我们将调用implementation方法,该方法不使用谓词作为输入,仅对已过滤的集合进行迭代。

而且,据我所知,

WhereListIterator迭代器避免了间接虚拟表调用,而是直接调用迭代器方法。

并且,这就是这种加速的原因。

1
投票
[我刚刚进行了测试,您可以在.Net小提琴[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


0
投票
它们在功能上等效,并且等效。 LINQ建立一个查询,直到枚举结果(例如foreach循环或本例中的First()操作。

0
投票
我认为您的问题更像是:
© www.soinside.com 2019 - 2024. All rights reserved.