c# - ELI5 : How does converting an IEnumerable to a list or array avoid the performance penalty of multiple enumeration of IEnumerable?

标签 c# resharper ienumerable enumeration

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/

相关文章:

c# - 判断可能出现的字符串赋值运算符异常

c# - ASP.NET Core 在 ExternalLoginSignInAsync 之后获取 UserId

c# - 如何绑定(bind) ctrl+1 以选择第一个选项卡?

ReSharper 与 Stylecop 因使用指令指令 SA1210 SA1211 发生冲突

c# - 立即返回 IEnumerable<T> 或转换为 List<T>?

c# - base64string 可以包含的最大字符数是多少

c# - 使用动态关键字转换泛型类型是否会导致装箱?

c# - 为什么 Resharper 无法识别我的网络引用?

c# - Yield Return == IEnumerable 和 IEnumerator 是吗?

c# - Enumerator.MoveNext() 在第一次调用时抛出 'Collection was Modified'