我正在进行性能测试并发现像这样的一个 LINQ 表达式:
result = list.First(f => f.Id == i).Property
比......慢
result = list.Where(f => f.Id == i).First().Property
这似乎有些反直觉。我本以为第一个表达式会更快,因为在谓词满足时可以立即停止迭代整个列表,而我本以为使用 .Where()
表达式可能需要在调用结果子集的 .First()
之前遍历整个列表。即使后者采用了短路计算,它也不应该比直接使用 First 更快,但实际上却是这样。
以下是两个非常简单的单元测试,说明了这一点。 在 .Net 和 Silverlight 4 上启用优化编译时,TestWhereAndFirst 比 TestFirstOnly 快约 30%。 我已经尝试让谓词返回更多结果,但性能差异相同。
有人能解释一下为什么 .First(fn)
比 .Where(fn).First()
更慢吗?我发现 .Count(fn)
与 .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);
}
First()
时,它将查询(Where(...)
的返回值)仅匹配一次并永远不会再次查询。因此,检查的元素数量与直接使用谓词调用First(...)
时完全相同。 - Jon.Where().First()
是 0.021 秒,而.First()
是 0.037 秒。这是使用一个简单的int
列表。 - Ry-Reset()
方法;你的测试实际上显示了First()
要快得多。 - Jay