Resharper 不断提示这一点:可能存在 IEnumerable 的多重枚举。例如:
private int ParseLoanNumber(IEnumerable<string> lines)
{
var loanNumber = 0;
var item = lines.FirstOrDefault(l => l.StartsWith(" LN# 00"));
if (item != null)
{
loanNumber = item.ParseInt(8, 10).GetValueOrDefault();
}
else
{
item = lines.FirstOrDefault(l => l.StartsWith(" LOAN-NO (CONT'D) 00"));
if (item != null)
{
loanNumber = item.ParseInt(19, 10).GetValueOrDefault();
}
}
// Yada yada...
}
推荐的解决方案是将可枚举
转换为列表
或数组
,然后对其进行迭代。
这让我很困惑。您仍然会枚举某些内容,并且两种类型(数组和列表)都实现 IEnumerable
。那么这如何解决任何问题,或以任何方式提高性能呢?
最佳答案
因为你可以这样写:
public IEnumerable<int> GetNumbersSlowly()
{
for (var i = 0; i < 100; i++)
{
Thread.Sleep(10000); //Or retrieve from a website, etc
yield return i;
}
}
如果你像这样使用它:
var numbers = GetNumbersSlowly();
foreach(var number in numbers) {
//Do something
}
foreach(var number in numbers) {
//Do something
}
这意味着每个数字完成的工作( sleep )两次。对可枚举进行一次评估并将其存储在数组或列表中意味着您确定没有进行额外的处理来返回项目。
既然您正在获取 IEnumerable<string>
,您确实不知道调用者没有执行上述操作。
如果您认为我的示例可能很少见或属于边缘情况,它也适用于这样的事情:
var someSource = new List<int> { 1, 2, 3, 4, 5 };
var numbers = someSource.Select(s => s * 100000);
现在每次迭代 numbers
,你还要重新进行计算。在这种情况下,这并不是什么工作,为什么要做得比你需要的更多(而且这是不平凡的工作并不罕见)。
关于c# - ELI5 : How does converting an IEnumerable to a list or array avoid the performance penalty of multiple enumeration of IEnumerable?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36345151/