我正在做一些性能测试,发现LINQ表达式

result = list.First(f => f.Id == i).Property

result = list.Where(f => f.Id == i).First().Property

这似乎有违直觉.我本以为第一个表达式会更快,因为它可以在满足谓词后立即停止迭代列表,而我会认为.Where()表达式可能会在对结果子集调用.First()之前迭代整个列表.即使后者确实短路了,它也不应该比直接使用第一个快,但它确实是快的.

下面是两个非常简单的单元测试来说明这一点.当在TestWherendFirst上进行优化编译时,比仅在TestFirstOnly上编译快约30%.Net和Silverlight 4.我try 过让谓词返回更多结果,但性能差异是相同的.

Can any one explain why .First(fn).Where(fn).First()? I see a similar counter intuitive result with .Count(fn) compared to .Where(fn).Count().

private const int Range = 50000;

private class Simple
{
   public int Id { get; set; }
   public int Value { get; set; }
}

[TestMethod()]
public void TestFirstOnly()
{
   List<Simple> list = new List<Simple>(Range);
   for (int i = Range - 1; i >= 0; --i)
   {
      list.Add(new Simple { Id = i, Value = 10 });
   }

   int result = 0;
   for (int i = 0; i < Range; ++i)
   {
      result += list.First(f => f.Id == i).Value;
   }

   Assert.IsTrue(result > 0);
}

[TestMethod()]
public void TestWhereAndFirst()
{
   List<Simple> list = new List<Simple>(Range);
   for (int i = Range - 1; i >= 0; --i)
   {
      list.Add(new Simple { Id = i, Value = 10 });
   }

   int result = 0;
   for (int i = 0; i < Range; ++i)
   {
      result += list.Where(f => f.Id == i).First().Value;
   }

   Assert.IsTrue(result > 0);
}

推荐答案

我得到了同样的结果:where+first比first快.

正如Jon所指出的,Linq使用惰性判断,因此这两种方法的性能应该(并且是)大致相似.

在Reflector中,首先使用一个简单的foreach循环来迭代集合,但其中有各种专门针对不同集合类型(数组、列表等)的迭代器.大概这就是小优势所在.

.net相关问答推荐

从Couchbase删除_txn文档的推荐方法?""

避免函数和其他对象之间的相互递归的模式?

从删除项目时重新索引的列表中删除项目的最佳算法是什么?

在 .NET 中使用 AES 解密时缺少后半字节

如何规范机器之间连字符的排序顺序?

如何计算给定2个字符串的距离相似性度量?

关于在 .NET 中干净地终止线程的问题

比较 C# 中的双精度值

ICommand MVVM 实现

在 WinForms 应用程序中查找焦点控件的首选方法是什么?

使用返回随机结果的函数进行单元测试

使用 C# 清除文本文件的内容

无法将文件 *.mdf 作为数据库附加

清除 .NET 的 StringBuilder 内容的最佳方法

从 .NET 中的字符串末尾修剪字符串 - 为什么会丢失?

MemoryStream.Close() 或 MemoryStream.Dispose()

String.Replace() 与 StringBuilder.Replace()

.NET 的黄瓜替代品

通过继承扩展枚举

检测到包降级警告(dotnet core,vs 2017)