使用.First()和.Where()之间的区别。第一个()

时间:2013-06-06 13:52:26

标签: c# linq

这有什么区别:

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

和此:

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

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

7 个答案:

答案 0 :(得分:4)

除了样式偏好

之外没有其他区别

答案 1 :(得分:3)

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

答案 2 :(得分:3)

Where针对不同类型的集合类型进行了特殊优化,而FirstSingleCount等其他方法则不利用集合的类型。

因此Where(predicate).First()能够进行First(predicate)没有的优化。

老实说,这是不好的实施。

答案 3 :(得分:2)

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

答案 4 :(得分:2)

这取决于。如果LINQ正在转换为SQL,那么它取决于如何处理转换。如果你正在使用LINQ到对象(例如你正在查看现有的内存数组)那么,虽然最终结果相同,但性能却明显不同。我跑了一些基准,实际上对结果感到惊讶。我会假设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

答案 5 :(得分:-3)

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

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

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

因此,使用.First(item => item == 0)可能会提高效率。

答案 6 :(得分:-4)

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

因此使用.First()应该更有效率。除非你的编译器足够聪明,只能执行First()。