所以我有一个相当标准的 LINQ-to-Object 设置。
var query = expensiveSrc.Where(x=> x.HasFoo)
.OrderBy(y => y.Bar.Count())
.Select(z => z.FrobberName);
// ...
if (!condition && !query.Any())
return; // seems to enumerate and sort entire enumerable
// ...
foreach (var item in query)
// ...
这将所有内容枚举两次。哪个不好。
var queryFiltered = expensiveSrc.Where(x=> x.HasFoo);
var query = queryFiltered.OrderBy(y => y.Bar.Count())
.Select(z => z.FrobberName);
if (!condition && !queryFiltered.Any())
return;
// ...
foreach (var item in query)
// ...
有效,但有更好的方法吗?
是否有任何非疯狂的方式来“启发” Any() 绕过非必需的操作?我想我记得这种优化进入 EduLinq。
最佳答案
为什么不直接去掉多余的:
if (!query.Any())
return;
它似乎真的没有任何用途——即使没有它,
foreach
的主体如果查询没有结果,则不会执行。所以使用 Any()
checkin ,您在快速路径中不保存任何内容,并在慢速路径中枚举两次。另一方面,如果您必须知道循环结束后是否找到任何结果,您不妨只使用一个标志:
bool itemFound = false;
foreach (var item in query)
{
itemFound = true;
... // Rest of the loop body goes here.
}
if(itemFound)
{
// ...
}
或者,如果您真的担心循环体中的冗余标志设置,您可以直接使用枚举器:
using(var erator = query.GetEnumerator())
{
bool itemFound = erator.MoveNext();
if(itemFound)
{
do
{
// Do something with erator.Current;
} while(erator.MoveNext())
}
// Do something with itemFound
}
关于linq - 使用 Any() 时优化 OrderBy(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8980806/