4

这之间有什么区别:

myList.Where(item => item == 0).First();

还有这个:

myList.First(item => item == 0);

后者对我来说更有意义,因为它更短,但我似乎更经常看到顶级版本。

4

7 回答 7

5

除了风格偏好没有区别

于 2013-06-06T13:54:01.630 回答
4

Where对不同类型的集合类型进行特殊优化,而其他方法如First,SingleCount没有利用集合的类型。

所以Where(predicate).First()能够做一些First(predicate)没有的优化。

老实说,这是一个糟糕的实施。

于 2014-01-17T20:21:58.900 回答
3

不,本地查询没有区别。前Where一种语法是多余的。

于 2013-06-06T13:53:53.157 回答
2

“可能不会” - 这可能取决于 Linq 查询是否会导致翻译成另一种语言 - 例如 SQL

于 2013-06-06T13:54:49.010 回答
2

这取决于。如果 LINQ 正在转换为一段 SQL,那么它取决于如何处理该转换。如果您使用 LINQ to 对象(例如,您正在查看内存中的现有数组),那么虽然最终结果相同,但性能明显不同。我做了一些基准测试,实际上对结果感到惊讶。我会假设这array.First()会比 更有效array.Where(...).First(),但我发现它是相反的。

我创建了一个测试,为了查看遍历数组需要多长时间,我将搜索项放在数组的最后。我对每个测试做了 200 次测试,每个测试包含 1000 次迭代。以 Ticks 为单位的平均结果是:

First()         = 2655969
Where().First() = 1455211 

如您所见Where().First(),大约需要大约一半的First()单独时间。

我的基准测试应用程序如下:

class Program
{
  private const int internalIterations = 1000;
  private const int externalIterations = 100;
  private const int dataSize = 100000;
  private const int search = dataSize - 1;

  private static readonly long[] resultsFirst = new long[externalIterations*2];
  private static readonly long[] resultsWhereFirst = new long[externalIterations*2];
  private static readonly int[] data = Enumerable.Range(0, dataSize).ToArray();

  static void Main(string[] args)
  {
    Stopwatch sw = new Stopwatch();
    for (int i = 0; i < externalIterations; i++)
    {
      Console.WriteLine("Iteration {0} of {1}", i+1, externalIterations);
      sw.Restart();
      First();
      sw.Stop();
      resultsFirst[i*2] = sw.ElapsedTicks;
      Console.WriteLine("     First : {0}", sw.ElapsedTicks);

      sw.Restart();
      WhereFirst();
      sw.Stop();
      resultsWhereFirst[i*2] = sw.ElapsedTicks;
      Console.WriteLine("WhereFirst : {0}", sw.ElapsedTicks);

      sw.Restart();
      WhereFirst();
      sw.Stop();
      resultsWhereFirst[(i*2)+1] = sw.ElapsedTicks;
      Console.WriteLine("WhereFirst : {0}", sw.ElapsedTicks);

      sw.Restart();
      First();
      sw.Stop();
      resultsFirst[(i*2)+1] = sw.ElapsedTicks;
      Console.WriteLine("     First : {0}", sw.ElapsedTicks);
    }

    Console.WriteLine("Done!");
    Console.WriteLine("Averages:");
    Console.WriteLine("     First Average: {0:0.00}", resultsFirst.Average());
    Console.WriteLine("WhereFirst Average: {0:0.00}", resultsWhereFirst.Average());

  }

  private static void WhereFirst()
  {
    for (int i = 0; i < internalIterations; i++)
    {
      int item = data.Where(d => d == search).First();
    }
  }

  private static void First()
  {
    for (int i = 0; i < internalIterations; i++)
    {
      int item = data.First(d => d == search);
    }
  }
}

更新

我尝试使用 List 而不是数组作为数据源,发现它比较慢。

数据创建行如下所示:

private static readonly List<int> data = Enumerable.Range(0, dataSize).ToList();

最终结果是:

First()         = 3222609
Where().First() = 2124652
于 2013-06-06T14:35:58.347 回答
-3

在功能上,它们是相同的,但是,.First(...)单独使用可能更有效。

  • .Where(item => item == 0)将扫描整个项目列表并将所有符合条件的项目收集到一个列表中。在该列表上应用.First()将选择第一项。

  • .First(item => item == 0)可以扫描列表直到找到第一个匹配项,然后在找到第一个匹配项时停止。

所以使用.First(item => item == 0)可能最终会更有效率。

于 2013-06-06T14:02:50.453 回答
-5

.First() 将迭代您的列表,直到找到您的项目。.Where() 将迭代您的整个列表。

所以使用 .First() 应该更有效。除非您的编译器足够聪明,可以只执行 First()。

于 2013-06-06T13:57:37.923 回答